diff --git a/.ai/categories/smart-contracts.md b/.ai/categories/smart-contracts.md index 1e901e36e..a08beab83 100644 --- a/.ai/categories/smart-contracts.md +++ b/.ai/categories/smart-contracts.md @@ -3680,2191 +3680,2355 @@ Now that you have the foundational knowledge to use Ethers.js with Polkadot Hub, --- -Page Title: Dual Virtual Machine Stack +Page Title: Deploy Contracts to Polkadot Hub with Web3.js -- 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. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-web3-js.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/libraries/web3-js/ +- Summary: Learn how to interact with Polkadot Hub using Web3.js, from compiling and deploying Solidity contracts to interacting with deployed smart contracts. -# Dual Virtual Machine Stack +# Web3.js + +!!! 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. -!!! 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). +Interacting with blockchains typically requires an interface between your application and the network. [Web3.js](https://web3js.readthedocs.io/){target=\_blank} offers this interface through a comprehensive collection of libraries, facilitating seamless interaction with the nodes using HTTP or WebSocket protocols. This guide illustrates how to utilize Web3.js specifically for interactions with Polkadot Hub. -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. +This guide is intended for developers who are familiar with JavaScript and want to interact with the Polkadot Hub using Web3.js. -## Migrate from EVM +## Prerequisites -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. +Before getting started, ensure you have the following installed: -REVM allows developers to use their existing Ethereum tooling and infrastructure to build on Polkadot. Choose REVM to: +- **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. -- 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. +## Project Structure -REVM enables Ethereum developers to seamlessly migrate to Polkadot, achieving performance and fee improvements without modifying their existing contracts or developer tooling stack. +This project organizes contracts, scripts, and compiled artifacts for easy development and deployment. -## Upgrade to PolkaVM +```text title="Web3.js Polkadot Hub" +web3js-project +├── contracts +│ ├── Storage.sol +├── scripts +│ ├── connectToProvider.js +│ ├── fetchLastBlock.js +│ ├── compile.js +│ ├── deploy.js +│ ├── updateStorage.js +├── abis +│ ├── Storage.json +├── artifacts +│ ├── Storage.bin +├── contract-address.json +├── node_modules/ +├── package.json +├── package-lock.json +└── README.md +``` -[**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: +## Set Up the Project -- 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. +To start working with Web3.js, create a new folder and initialize your project by running the following commands in your terminal: -The interpreter remains particularly beneficial for contracts with minimal code execution, as it enables immediate code execution through lazy interpretation. +```bash +mkdir web3js-project +cd web3js-project +npm init -y +``` -## Architecture +## Install Dependencies -The following key components of PolkaVM work together to enable Ethereum compatibility on Polkadot-based chains. +Next, run the following command to install the Web3.js library: -### Revive Pallet +```bash +npm install web3 +``` -[**`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: +Add the Solidity compiler so you can generate standard EVM bytecode: -```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 +```bash +npm install --save-dev solc ``` -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. +!!! tip + The sample scripts use ECMAScript modules. Add `"type": "module"` to your `package.json` (or rename the files to `.mjs`) so that `node` can run the `import` statements. -### PolkaVM Design Fundamentals +## Set Up the Web3 Provider -PolkaVM differs from the EVM in two key ways that make it faster, more hardware-efficient, and easier to extend: +The provider configuration is the foundation of any Web3.js application. It serves as a bridge between your application and the blockchain, allowing you to query blockchain data and interact with smart contracts. -- **Register-based design**: Instead of a stack machine, PolkaVM uses a RISC-V–style register model. This design: +To interact with Polkadot Hub, you must set up a Web3.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: - - 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. +```js title="scripts/connectToProvider.js" +const { Web3 } = require('web3'); -- **64-bit word size**: PolkaVM runs on a native 64-bit word size, aligning directly with modern CPUs. This design: +const createProvider = (rpcUrl) => { + const web3 = new Web3(rpcUrl); + return web3; +}; - - 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. +const PROVIDER_RPC = { + rpc: 'INSERT_RPC_URL', + chainId: 'INSERT_CHAIN_ID', + name: 'INSERT_CHAIN_NAME', +}; -## Where To Go Next +createProvider(PROVIDER_RPC.rpc); -
+``` -- Learn __Contract Deployment__ +!!! 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' + }; + ``` - Learn how REVM and PVM compare for compiling and deploying smart contracts. +To connect to the provider, execute: - [:octicons-arrow-right-24: Reference](/smart-contracts/for-eth-devs/contract-deployment/) +```bash +node scripts/connectToProvider.js +``` -
+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 { Web3 } = require('web3'); -Page Title: Ethereum-Native Precompiles + const createProvider = (rpcUrl) => { + const web3 = new Web3(rpcUrl); + return web3; + }; -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles-eth-native.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/precompiles/eth-native/ -- Summary: General overview of Ethereum-native precompiles in Polkadot Hub’s Revive pallet, including usage basics and details on standard precompiles for smart contracts. + const PROVIDER_RPC = { + rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', + chainId: 420420422, + name: 'polkadot-hub-testnet', + }; -# Ethereum-Native Precompiles + const main = async () => { + try { + const web3 = createProvider(PROVIDER_RPC.rpc); + const latestBlock = await web3.eth.getBlockNumber(); + console.log('Last block: ' + latestBlock); + } catch (error) { + console.error('Error connecting to Polkadot Hub TestNet: ' + error.message); + } + }; -## Introduction + main(); -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. + ``` -In Polkadot Hub's Revive pallet, these precompiles maintain compatibility with standard Ethereum addresses, allowing developers familiar with Ethereum to seamlessly transition their smart contracts while benefiting from the performance optimizations of the PolkaVM runtime. +## Compile Contracts -## How to Use Precompiles +Polkadot Hub exposes an Ethereum JSON-RPC endpoint, so you can compile Solidity contracts to familiar EVM bytecode with the upstream [`solc`](https://www.npmjs.com/package/solc){target=\_blank} compiler. The resulting artifacts work with any EVM-compatible toolchain and can be deployed through Web3.js. -To use a precompile in your smart contract, simply call the precompile's address as you would any other contract. Each precompile has a specific address (shown in the table below) and expects input data in a particular format. The precompile executes natively at the runtime level and returns the result directly to your contract. +### Sample Storage Smart Contract -For example, to use the ECRecover precompile to verify a signature, you would call address `0x0000000000000000000000000000000000000001` with the properly formatted signature data. The precompile handles the complex cryptographic operations efficiently and returns the recovered public key. +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. -You can find sample contracts for each precompile in the [`precompiles-hardhat`](https://github.com/polkadot-developers/polkavm-hardhat-examples/tree/master/precompiles-hardhat/contracts){target=\_blank} project. +```solidity title="contracts/Storage.sol" +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; -## Standard Precompiles in Polkadot Hub +contract Storage { + // Public state variable to store a number + uint256 public storedNumber; -Revive implements the standard set of Ethereum precompiles: + /** + * 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; + } +} +``` -| Contract Name | Address (Last Byte) | Description | -| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------: | :---------------------------------------------------------------------------------------------: | -| [ECRecover](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2503/substrate/frame/revive/src/pure_precompiles/ecrecover.rs){target=\_blank} | 0x01 | Recovers the public key associated with a signature | -| [Sha256](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2503/substrate/frame/revive/src/pure_precompiles/sha256.rs){target=\_blank} | 0x02 | Implements the SHA-256 hash function | -| [Ripemd160](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2503/substrate/frame/revive/src/pure_precompiles/ripemd160.rs){target=\_blank} | 0x03 | Implements the RIPEMD-160 hash function | -| [Identity](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2503/substrate/frame/revive/src/pure_precompiles/identity.rs){target=\_blank} | 0x04 | Data copy function (returns input as output) | -| [Modexp](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2503/substrate/frame/revive/src/pure_precompiles/modexp.rs){target=\_blank} | 0x05 | Modular exponentiation | -| [Bn128Add](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2503/substrate/frame/revive/src/pure_precompiles/bn128.rs#L27){target=\_blank} | 0x06 | Addition on the [alt_bn128 curve](https://eips.ethereum.org/EIPS/eip-196){target=\_blank} | -| [Bn128Mul](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2503/substrate/frame/revive/src/pure_precompiles/bn128.rs#L48){target=\_blank} | 0x07 | Multiplication on the [alt_bn128 curve](https://eips.ethereum.org/EIPS/eip-196){target=\_blank} | -| [Bn128Pairing](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2503/substrate/frame/revive/src/pure_precompiles/bn128.rs#L69){target=\_blank} | 0x08 | Pairing check on the alt_bn128 curve | -| [Blake2F](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2503/substrate/frame/revive/src/pure_precompiles/blake2f.rs){target=\_blank} | 0x09 | Blake2 compression function F | +### Compile the Smart Contract -## Conclusion +To compile this contract, use the following script: -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. +```js title="scripts/compile.js" +const solc = require('solc'); +const { readFileSync, writeFileSync, mkdirSync, existsSync } = require('fs'); +const { basename, join } = require('path'); +const ensureDir = (dirPath) => { + if (!existsSync(dirPath)) { + mkdirSync(dirPath, { recursive: true }); + } +}; ---- +const compileContract = (solidityFilePath, abiDir, artifactsDir) => { + try { + // Read the Solidity file + const source = readFileSync(solidityFilePath, 'utf8'); + const fileName = basename(solidityFilePath); + + // Construct the input object for the Solidity compiler + const input = { + language: 'Solidity', + sources: { + [fileName]: { + content: source, + }, + }, + settings: { + outputSelection: { + '*': { + '*': ['abi', 'evm.bytecode'], + }, + }, + }, + }; + + console.log(`Compiling contract: ${fileName}...`); + + // Compile the contract + const output = JSON.parse(solc.compile(JSON.stringify(input))); + + // Check for errors + if (output.errors) { + const errors = output.errors.filter(error => error.severity === 'error'); + if (errors.length > 0) { + console.error('Compilation errors:'); + errors.forEach(err => console.error(err.formattedMessage)); + return; + } + // Show warnings + const warnings = output.errors.filter(error => error.severity === 'warning'); + warnings.forEach(warn => console.warn(warn.formattedMessage)); + } + + // Ensure output directories exist + ensureDir(abiDir); + ensureDir(artifactsDir); + + // Process compiled contracts + for (const [sourceFile, contracts] of Object.entries(output.contracts)) { + for (const [contractName, contract] of Object.entries(contracts)) { + console.log(`Compiled contract: ${contractName}`); + + // Write the ABI + const abiPath = join(abiDir, `${contractName}.json`); + writeFileSync(abiPath, JSON.stringify(contract.abi, null, 2)); + console.log(`ABI saved to ${abiPath}`); + + // Write the bytecode + const bytecodePath = join(artifactsDir, `${contractName}.bin`); + writeFileSync(bytecodePath, contract.evm.bytecode.object); + console.log(`Bytecode saved to ${bytecodePath}`); + } + } + } catch (error) { + console.error('Error compiling contracts:', error); + } +}; -Page Title: Faucet +const solidityFilePath = join(__dirname, '../contracts/Storage.sol'); +const abiDir = join(__dirname, '../abis'); +const artifactsDir = join(__dirname, '../artifacts'); -- 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. +compileContract(solidityFilePath, abiDir, artifactsDir); +``` -# Faucet +!!! 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. -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: +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 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. +Execute the script above by running: +```bash +node scripts/compile.js +``` -## Get Test Tokens +After executing the script, the Solidity contract is compiled into standard EVM bytecode. The ABI and bytecode are saved into files with `.json` and `.bin` extensions, respectively. You can now proceed with deploying the contract to Polkadot Hub, as outlined in the next section. -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: +## Deploy the Compiled Contract -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. +To deploy your compiled contract to Polkadot Hub, you'll need a wallet with a private key to sign the deployment transaction. -![Polkadot Faucet](/images/smart-contracts/faucet/faucet-1.gif) +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: -## Things to Consider +1. Set up the required imports and utilities: -!!! 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. + ```js title="scripts/deploy.js" + const { writeFileSync, existsSync, readFileSync } = require('fs'); + const { join } = require('path'); + const { Web3 } = require('web3'); -!!! 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. + const scriptsDir = __dirname; + const abisDir = join(__dirname, '../abis'); + const artifactsDir = join(__dirname, '../artifacts'); + ``` -## Using Your Test Tokens +2. Create a provider to connect to Polkadot Hub: -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. + ```js title="scripts/deploy.js" + const createProvider = (rpcUrl, chainId, chainName) => { + const web3 = new Web3(rpcUrl); + return web3; + }; + ``` +3. Set up functions to read contract artifacts: ---- + ```js title="scripts/deploy.js" + const getAbi = (contractName) => { + try { + const abiPath = join(abisDir, `${contractName}.json`); + return JSON.parse(readFileSync(abiPath, 'utf8')); + } catch (error) { + console.error( + `Could not find ABI for contract ${contractName}:`, + error.message, + ); + throw error; + } + }; -Page Title: Get Started with Parachain Development + const getByteCode = (contractName) => { + try { + const bytecodePath = join(artifactsDir, `${contractName}.bin`); + const bytecode = readFileSync(bytecodePath, 'utf8').trim(); + return bytecode.startsWith('0x') ? bytecode : `0x${bytecode}`; + } catch (error) { + console.error( + `Could not find bytecode for contract ${contractName}:`, + error.message, + ); + throw error; + } + }; + ``` -- 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. +4. Create the main deployment function: -# Get Started + ```js title="scripts/deploy.js" + const deployContract = async (contractName, privateKey, providerConfig) => { + console.log(`Deploying ${contractName}...`); + try { + const web3 = createProvider( + providerConfig.rpc, + providerConfig.chainId, + providerConfig.name, + ); -The following sections provide practical recipes for building parachains on Polkadot—each focused on specific development scenarios with step-by-step, hands-on examples. + const formattedPrivateKey = privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`; + const account = web3.eth.accounts.privateKeyToAccount(formattedPrivateKey); + web3.eth.accounts.wallet.add(account); + web3.eth.defaultAccount = account.address; -## Quick Start Guides + const abi = getAbi(contractName); + const bytecode = getByteCode(contractName); + const contract = new web3.eth.Contract(abi); + const deployTx = contract.deploy({ + data: bytecode, + }); -Quick start guides help developers set up and interact with the Polkadot parachain ecosystem using various tools and frameworks. + const gas = await deployTx.estimateGas(); + const gasPrice = await web3.eth.getGasPrice(); -| 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 | + console.log(`Estimated gas: ${gas}`); + console.log(`Gas price: ${web3.utils.fromWei(gasPrice, 'gwei')} gwei`); -## Launch a Simple Parachain + const deployedContract = await deployTx.send({ + from: account.address, + gas: gas, + gasPrice: gasPrice, + }); -Learn the fundamentals of launching and deploying a parachain to the Polkadot network. + const address = deployedContract.options.address; + console.log(`Contract ${contractName} deployed at: ${address}`); -| 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) | + const addressesFile = join(scriptsDir, 'contract-address.json'); + const addresses = existsSync(addressesFile) + ? JSON.parse(readFileSync(addressesFile, 'utf8')) + : {}; -## Customize Your Runtime + addresses[contractName] = address; + writeFileSync(addressesFile, JSON.stringify(addresses, null, 2), 'utf8'); + } catch (error) { + console.error(`Failed to deploy contract ${contractName}:`, error); + } + }; + ``` -Build custom functionality for your parachain by composing and creating pallets. +5. Configure and execute the deployment: -| 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 | + ```js title="scripts/deploy.js" + const providerConfig = { + rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', // TODO: replace to `https://services.polkadothub-rpc.com/testnet` when ready + chainId: 420420422, + name: 'polkadot-hub-testnet', + }; -### Pallet Development + const privateKey = 'INSERT_PRIVATE_KEY'; -Deep dive into creating and managing custom pallets for your parachain. + deployContract('Storage', privateKey, providerConfig); + ``` -| 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 | + !!! note -## Testing + A private key is a hexadecimal string that is used to sign and pay for the deployment transaction. **Always keep your private key secure and never share it publicly**. -Test your parachain in various environments before production deployment. + Ensure to replace the `INSERT_PRIVATE_KEY` placeholder with your actual private key. -| 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 | +??? code "View complete script" -## Runtime Upgrades and Maintenance + ```js title="scripts/deploy.js" + const { writeFileSync, existsSync, readFileSync } = require('fs'); + const { join } = require('path'); + const { Web3 } = require('web3'); -Manage your parachain's lifecycle with forkless upgrades and maintenance operations. + const scriptsDir = __dirname; + const abisDir = join(__dirname, '../abis'); + const artifactsDir = join(__dirname, '../artifacts'); -| 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 | + const createProvider = (rpcUrl, chainId, chainName) => { + const web3 = new Web3(rpcUrl); + return web3; + }; -## Interoperability + const getAbi = (contractName) => { + try { + const abiPath = join(abisDir, `${contractName}.json`); + return JSON.parse(readFileSync(abiPath, 'utf8')); + } catch (error) { + console.error( + `Could not find ABI for contract ${contractName}:`, + error.message, + ); + throw error; + } + }; -Configure your parachain for cross-chain communication using XCM (Cross-Consensus Messaging). + const getByteCode = (contractName) => { + try { + const bytecodePath = join(artifactsDir, `${contractName}.bin`); + const bytecode = readFileSync(bytecodePath, 'utf8').trim(); + return bytecode.startsWith('0x') ? bytecode : `0x${bytecode}`; + } catch (error) { + console.error( + `Could not find bytecode for contract ${contractName}:`, + error.message, + ); + throw error; + } + }; -| 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 | + const deployContract = async (contractName, privateKey, providerConfig) => { + console.log(`Deploying ${contractName}...`); + try { + const web3 = createProvider( + providerConfig.rpc, + providerConfig.chainId, + providerConfig.name, + ); -## Integrations + const formattedPrivateKey = privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`; + const account = web3.eth.accounts.privateKeyToAccount(formattedPrivateKey); + web3.eth.accounts.wallet.add(account); + web3.eth.defaultAccount = account.address; -Integrate your parachain with essential ecosystem tools and services. + const abi = getAbi(contractName); + const bytecode = getByteCode(contractName); + const contract = new web3.eth.Contract(abi); + const deployTx = contract.deploy({ + data: bytecode, + }); -| 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 | + const gas = await deployTx.estimateGas(); + const gasPrice = await web3.eth.getGasPrice(); -## Additional Resources + console.log(`Estimated gas: ${gas}`); + console.log(`Gas price: ${web3.utils.fromWei(gasPrice, 'gwei')} gwei`); -- [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/) + const deployedContract = await deployTx.send({ + from: account.address, + gas: gas, + gasPrice: gasPrice, + }); + const address = deployedContract.options.address; + console.log(`Contract ${contractName} deployed at: ${address}`); ---- + const addressesFile = join(scriptsDir, 'contract-address.json'); + const addresses = existsSync(addressesFile) + ? JSON.parse(readFileSync(addressesFile, 'utf8')) + : {}; -Page Title: Get Started with Smart Contracts + addresses[contractName] = address; + writeFileSync(addressesFile, JSON.stringify(addresses, null, 2), 'utf8'); + } catch (error) { + console.error(`Failed to deploy contract ${contractName}:`, error); + } + }; -- 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. + const providerConfig = { + rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', // TODO: replace to `https://services.polkadothub-rpc.com/testnet` when ready + chainId: 420420422, + name: 'polkadot-hub-testnet', + }; -# Get Started + const privateKey = 'INSERT_PRIVATE_KEY'; -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. + deployContract('Storage', privateKey, providerConfig); -## 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 | +To run the script, execute the following command: -## Build and Test Locally +```bash +node scripts/deploy.js +``` -Set up local environments and CI-friendly workflows to iterate quickly and validate changes before deploying. +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. -| 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 | +## Interact with the Contract -## Ethereum Developer Resources +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 `updateStorage.js` in the root of your project and add the following code: -Bridge your Ethereum knowledge with Polkadot Hub specifics: account mapping, fees, JSON‑RPC, and deployment. +```js title="scripts/updateStorage.js" +const { readFileSync } = require('fs'); +const { join } = require('path'); +const { Web3 } = require('web3'); -| 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 | +const abisDir = join(__dirname, '../abis'); -## Cookbook: Hands‑on Tutorials +const getAbi = (contractName) => { + try { + const abiPath = join(abisDir, `${contractName}.json`); + return JSON.parse(readFileSync(abiPath, 'utf8')); + } catch (error) { + console.error( + `Could not find ABI for contract ${contractName}:`, + error.message, + ); + throw error; + } +}; -Follow step‑by‑step guides that walk through common tasks and complete dApp examples. +const updateStorage = async (config) => { + try { + const web3 = new Web3(config.rpcUrl); + const formattedPrivateKey = config.privateKey.startsWith('0x') ? config.privateKey : `0x${config.privateKey}`; + const account = web3.eth.accounts.privateKeyToAccount(formattedPrivateKey); + web3.eth.accounts.wallet.add(account); -| 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 | + const abi = getAbi('Storage'); + const contract = new web3.eth.Contract(abi, config.contractAddress); -## Libraries + const initialValue = await contract.methods.storedNumber().call(); + console.log('Current stored value:', initialValue); -Choose the client libraries that fit your stack for connecting wallets and calling contracts. + const updateTransaction = contract.methods.setNumber(1); + const gasEstimate = await updateTransaction.estimateGas({ + from: account.address, + }); + const gasPrice = await web3.eth.getGasPrice(); -| 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 | + const receipt = await updateTransaction.send({ + from: account.address, + gas: gasEstimate, + gasPrice: gasPrice, + }); -## Integrations + console.log(`Transaction hash: ${receipt.transactionHash}`); -Integrate essential services like wallets, indexers, and oracles to round out your dApp. + const newValue = await contract.methods.storedNumber().call(); + console.log('New stored value:', newValue); -| 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 | + return receipt; + } catch (error) { + console.error('Update failed:', error); + throw error; + } +}; -## Precompiles +const config = { + rpcUrl: 'https://testnet-passet-hub-eth-rpc.polkadot.io', + privateKey: 'INSERT_PRIVATE_KEY', + contractAddress: 'INSERT_CONTRACT_ADDRESS', +}; -Discover precompiled system contracts available on the Hub and how to use them. +updateStorage(config) + .then((receipt) => console.log('Update successful')) + .catch((error) => console.error('Update error')); +``` -| 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 | +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. The script prints the balance for `ADDRESS_TO_CHECK` before it writes and doubles the stored value, so pick any account you want to monitor. -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 interact with the contract, run: +```bash +node scripts/updateStorage.js +``` ---- +## Where to Go Next -Page Title: Glossary +Now that you have the foundational knowledge to use Web3.js with Polkadot Hub, you can: -- 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. +- **Dive into Web3.js utilities**: Discover additional Web3.js features, such as wallet management, signing messages, subscribing to events, etc. -# Glossary +- **Implement batch transactions**: Use Web3.js to execute batch transactions for efficient multi-step contract interactions. -Key definitions, concepts, and terminology specific to the Polkadot ecosystem are included here. +- **Build scalable applications**: Combine Web3.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). -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 +Page Title: Dual Virtual Machine Stack -The role in a blockchain that can participate in consensus mechanisms. +- 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. -- **[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). +# Dual Virtual Machine Stack -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. +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. +## Introduction -## Authority Round (Aura) +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). -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. +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. -Learn more by reading the official [Aura consensus algorithm](https://openethereum.github.io/Aura){target=\_blank} wiki article. +## Migrate from EVM -## Blind Assignment of Blockchain Extension (BABE) +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. -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. +REVM allows developers to use their existing Ethereum tooling and infrastructure to build on Polkadot. Choose REVM to: -Learn more by reading the official Web3 Foundation [BABE research document](https://research.web3.foundation/Polkadot/protocols/block-production/Babe){target=\_blank}. +- 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. -## Block Author +REVM enables Ethereum developers to seamlessly migrate to Polkadot, achieving performance and fee improvements without modifying their existing contracts or developer tooling stack. -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_. +## Upgrade to PolkaVM -## Byzantine Fault Tolerance (BFT) +[**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: -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. +- 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. -### Byzantine Failure +The interpreter remains particularly beneficial for contracts with minimal code execution, as it enables immediate code execution through lazy interpretation. -The loss of a network service due to node failures that exceed the proportion of nodes required to reach consensus. +## Architecture -### Practical Byzantine Fault Tolerance (pBFT) +The following key components of PolkaVM work together to enable Ethereum compatibility on Polkadot-based chains. -An early approach to Byzantine fault tolerance (BFT), practical Byzantine fault tolerance (pBFT) systems tolerate Byzantine behavior from up to one-third of participants. +### Revive Pallet -The communication overhead for such systems is `O(n²)`, where `n` is the number of nodes (participants) in the system. +[**`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: -### Preimage +```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 +``` -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. +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. -## Call +### PolkaVM Design Fundamentals -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. +PolkaVM differs from the EVM in two key ways that make it faster, more hardware-efficient, and easier to extend: -## Chain Specification +- **Register-based design**: Instead of a stack machine, PolkaVM uses a RISC-V–style register model. This design: -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. + - 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. -## Collator +- **64-bit word size**: PolkaVM runs on a native 64-bit word size, aligning directly with modern CPUs. This design: -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). + - 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. -More details are found on the [Polkadot Collator Wiki](https://wiki.polkadot.com/learn/learn-collator/){target=\_blank}. +## Where To Go Next -## 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. +- Learn __Contract Deployment__ -## 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. + Learn how REVM and PVM compare for compiling and deploying smart contracts. -See also [hybrid consensus](#hybrid-consensus). + [:octicons-arrow-right-24: Reference](/smart-contracts/for-eth-devs/contract-deployment/) -## 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. +Page Title: Ethereum-Native Precompiles -## Consensus Engine +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles-eth-native.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/precompiles/eth-native/ +- Summary: General overview of Ethereum-native precompiles in Polkadot Hub’s Revive pallet, including usage basics and details on standard precompiles for smart contracts. -The node subsystem responsible for consensus tasks. +# Ethereum-Native Precompiles -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. +## Introduction -See also [hybrid consensus](#hybrid-consensus). +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. -## Coretime +In Polkadot Hub's Revive pallet, these precompiles maintain compatibility with standard Ethereum addresses, allowing developers familiar with Ethereum to seamlessly transition their smart contracts while benefiting from the performance optimizations of the PolkaVM runtime. -The time allocated for utilizing a core, measured in relay chain blocks. There are two types of coretime: *on-demand* and *bulk*. +## How to Use Precompiles -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. +To use a precompile in your smart contract, simply call the precompile's address as you would any other contract. Each precompile has a specific address (shown in the table below) and expects input data in a particular format. The precompile executes natively at the runtime level and returns the result directly to your contract. -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}. +For example, to use the ECRecover precompile to verify a signature, you would call address `0x0000000000000000000000000000000000000001` with the properly formatted signature data. The precompile handles the complex cryptographic operations efficiently and returns the recovered public key. -## Development Phrase +You can find sample contracts for each precompile in the [`precompiles-hardhat`](https://github.com/polkadot-developers/polkavm-hardhat-examples/tree/master/precompiles-hardhat/contracts){target=\_blank} project. -A [mnemonic phrase](https://en.wikipedia.org/wiki/Mnemonic#For_numerical_sequences_and_mathematical_operations){target=\_blank} that is intentionally made public. +## Standard Precompiles in Polkadot Hub -Well-known development accounts, such as Alice, Bob, Charlie, Dave, Eve, and Ferdie, are generated from the same secret phrase: +Revive implements the standard set of Ethereum precompiles: -``` -bottom drive obey lake curtain smoke basket hold race lonely fit walk -``` +| Contract Name | Address (Last Byte) | Description | +| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------: | :---------------------------------------------------------------------------------------------: | +| [ECRecover](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2503/substrate/frame/revive/src/pure_precompiles/ecrecover.rs){target=\_blank} | 0x01 | Recovers the public key associated with a signature | +| [Sha256](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2503/substrate/frame/revive/src/pure_precompiles/sha256.rs){target=\_blank} | 0x02 | Implements the SHA-256 hash function | +| [Ripemd160](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2503/substrate/frame/revive/src/pure_precompiles/ripemd160.rs){target=\_blank} | 0x03 | Implements the RIPEMD-160 hash function | +| [Identity](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2503/substrate/frame/revive/src/pure_precompiles/identity.rs){target=\_blank} | 0x04 | Data copy function (returns input as output) | +| [Modexp](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2503/substrate/frame/revive/src/pure_precompiles/modexp.rs){target=\_blank} | 0x05 | Modular exponentiation | +| [Bn128Add](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2503/substrate/frame/revive/src/pure_precompiles/bn128.rs#L27){target=\_blank} | 0x06 | Addition on the [alt_bn128 curve](https://eips.ethereum.org/EIPS/eip-196){target=\_blank} | +| [Bn128Mul](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2503/substrate/frame/revive/src/pure_precompiles/bn128.rs#L48){target=\_blank} | 0x07 | Multiplication on the [alt_bn128 curve](https://eips.ethereum.org/EIPS/eip-196){target=\_blank} | +| [Bn128Pairing](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2503/substrate/frame/revive/src/pure_precompiles/bn128.rs#L69){target=\_blank} | 0x08 | Pairing check on the alt_bn128 curve | +| [Blake2F](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2503/substrate/frame/revive/src/pure_precompiles/blake2f.rs){target=\_blank} | 0x09 | Blake2 compression function F | -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`. +## Conclusion -## Digest +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. -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 +Page Title: Faucet -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. +- 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. -## Events +# Faucet -A means of recording that some particular [state](#state) transition happened. +Test tokens allow you to experiment with smart contracts, test transactions, and validate your dApp functionality without using real cryptocurrency. -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. +Polkadot has a faucet that distributes free TestNet tokens to developers for testing purposes: -## Executor +- 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. -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. +## Get Test Tokens -- 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. +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: -## Existential Deposit +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. -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. +![Polkadot Faucet](/images/smart-contracts/faucet/faucet-1.gif) -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. +## Things to Consider -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}. +!!! 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. -## Extrinsic +!!! 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. -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. +## Using Your Test Tokens -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). +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. -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. +Page Title: Get Started with Parachain Development -## FRAME (Framework for Runtime Aggregation of Modularized Entities) +- 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. -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. +# Get Started -[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} +The following sections provide practical recipes for building parachains on Polkadot—each focused on specific development scenarios with step-by-step, hands-on examples. -## Full Node +## Quick Start Guides -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. +Quick start guides help developers set up and interact with the Polkadot parachain ecosystem using various tools and frameworks. -## Genesis Configuration +| 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 | -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. +## Launch a Simple Parachain -## GRANDPA +Learn the fundamentals of launching and deploying a parachain to the Polkadot network. -A deterministic finality mechanism for blockchains that is implemented in the [Rust](https://www.rust-lang.org/){target=\_blank} programming language. +| 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) | -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}. +## Customize Your Runtime -## Header +Build custom functionality for your parachain by composing and creating pallets. -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. +| 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 | -## Hybrid Consensus +### Pallet Development -A blockchain consensus protocol that consists of independent or loosely coupled mechanisms for [block production](#block-author) and finality. +Deep dive into creating and managing custom pallets for your parachain. -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). +| 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 | -## Inherent Transactions +## Testing -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. +Test your parachain in various environments before production deployment. -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. +| 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 | -## JSON-RPC +## Runtime Upgrades and Maintenance -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. +Manage your parachain's lifecycle with forkless upgrades and maintenance operations. -For Polkadot SDK, this protocol is implemented through the [Parity JSON-RPC](https://github.com/paritytech/jsonrpc){target=\_blank} crate. +| 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 | -## Keystore +## Interoperability -A subsystem for managing keys for the purpose of producing new blocks. +Configure your parachain for cross-chain communication using XCM (Cross-Consensus Messaging). -## Kusama +| 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 | -[Kusama](https://kusama.network/){target=\_blank} is a Polkadot SDK-based blockchain that implements a design similar to the [Polkadot](#polkadot) network. +## Integrations -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}. +Integrate your parachain with essential ecosystem tools and services. -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. +| 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 | -## libp2p +## Additional Resources -A peer-to-peer networking stack that allows the use of many transport mechanisms, including WebSockets (usable in a web browser). +- [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/) -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. +Page Title: Get Started with Smart Contracts -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. +- 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. -## Metadata +# Get Started -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. +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. -## Nominated Proof of Stake (NPoS) +## Quick Starts -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. +Kick off development fast with curated links for connecting, funding, exploring, and deploying your first contract. -## Oracle +| 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 | -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. +## Build and Test Locally -## Origin +Set up local environments and CI-friendly workflows to iterate quickly and validate changes before deploying. -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}. +| 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 | -## Pallet +## Ethereum Developer Resources -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). +Bridge your Ethereum knowledge with Polkadot Hub specifics: account mapping, fees, JSON‑RPC, and deployment. -## Parachain +| 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 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}. +## Cookbook: Hands‑on Tutorials -## Paseo +Follow step‑by‑step guides that walk through common tasks and complete dApp examples. -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. +| 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 | -## Polkadot +## Libraries -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). +Choose the client libraries that fit your stack for connecting wallets and calling contracts. -## Polkadot Cloud +| 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 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. +## Integrations -## Polkadot Hub +Integrate essential services like wallets, indexers, and oracles to round out your dApp. -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. +| 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 | -## PolkaVM +## Precompiles -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. +Discover precompiled system contracts available on the Hub and how to use them. -## 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 | -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. +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. -## 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 +Page Title: Glossary -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. +- 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. -## Slot +# Glossary -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. +Key definitions, concepts, and terminology specific to the Polkadot ecosystem are included here. -## Sovereign Account +Additional glossaries from around the ecosystem you might find helpful: -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. +- [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} -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. +## Authority -## SS58 Address Format +The role in a blockchain that can participate in consensus mechanisms. -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 +- **[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). -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 +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. -## State Transition Function (STF) +## Authority Round (Aura) -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). +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. -## Storage Item +Learn more by reading the official [Aura consensus algorithm](https://openethereum.github.io/Aura){target=\_blank} wiki article. -[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. +## Blind Assignment of Blockchain Extension (BABE) -## Substrate +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. -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}. +Learn more by reading the official Web3 Foundation [BABE research document](https://research.web3.foundation/Polkadot/protocols/block-production/Babe){target=\_blank}. -## Transaction +## Block Author -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}. +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_. -## Transaction Era +## Byzantine Fault Tolerance (BFT) -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. +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. -## Trie (Patricia Merkle Tree) +### Byzantine Failure -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. +The loss of a network service due to node failures that exceed the proportion of nodes required to reach consensus. -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. +### Practical Byzantine Fault Tolerance (pBFT) -## Validator +An early approach to Byzantine fault tolerance (BFT), practical Byzantine fault tolerance (pBFT) systems tolerate Byzantine behavior from up to one-third of participants. -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 communication overhead for such systems is `O(n²)`, where `n` is the number of nodes (participants) in the system. -## WebAssembly (Wasm) +### Preimage -An execution architecture that allows for the efficient, platform-neutral expression of -deterministic, machine-executable logic. +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. -[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. +## Call -## Weight +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. -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. +## Chain Specification -The maximum block weight should be equivalent to one-third of the target block time with an allocation of one-third each for: +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. -- Block construction -- Network propagation -- Import and verification +## Collator -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. +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). -## Westend +More details are found on the [Polkadot Collator Wiki](https://wiki.polkadot.com/learn/learn-collator/){target=\_blank}. -Westend is a Parity-maintained, Polkadot SDK-based blockchain that serves as a test network for the [Polkadot](#polkadot) network. +## 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 -Page Title: Install Polkadot SDK +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. -- 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. +See also [hybrid consensus](#hybrid-consensus). -# Install Polkadot SDK +## Consensus Algorithm -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: +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). -- **Installing dependencies**: Setting up Rust, required system packages, and development tools. -- **Building the Polkadot SDK**: Cloning and compiling the Polkadot SDK repository. +Consensus algorithms are generally concerned with ensuring two properties: -Follow the appropriate section for your operating system to ensure all necessary tools are installed and configured properly. +- **Safety**: Indicating that all honest nodes eventually agreed on the state of the chain. +- **Liveness**: Indicating the ability of the chain to keep progressing. -## Install Dependencies: macOS +## Consensus Engine -You can install Rust and set up a Substrate development environment on Apple macOS computers with Intel or Apple M1 processors. +The node subsystem responsible for consensus tasks. -### Before You Begin {: #before-you-begin-mac-os } +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. -Before you install Rust and set up your development environment on macOS, verify that your computer meets the following basic requirements: +See also [hybrid consensus](#hybrid-consensus). -- 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. +## Coretime -### Install Homebrew +The time allocated for utilizing a core, measured in relay chain blocks. There are two types of coretime: *on-demand* and *bulk*. -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. +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. -To install Homebrew: +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}. -1. Open the Terminal application. -2. Download and install Homebrew by running the following command: +## Development Phrase - ```bash - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" - ``` +A [mnemonic phrase](https://en.wikipedia.org/wiki/Mnemonic#For_numerical_sequences_and_mathematical_operations){target=\_blank} that is intentionally made public. -3. Verify Homebrew has been successfully installed by running the following command: +Well-known development accounts, such as Alice, Bob, Charlie, Dave, Eve, and Ferdie, are generated from the same secret phrase: - ```bash - brew --version - ``` +``` +bottom drive obey lake curtain smoke basket hold race lonely fit walk +``` - The command displays output similar to the following: +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`. -
- brew --version - Homebrew 4.3.15 -
+## Digest -### Support for Apple Silicon +An extensible field of the [block header](#header) that encodes information needed by several actors in a blockchain network, including: -Protobuf must be installed before the build process can begin. To install it, run the following command: +- [Light clients](#light-client) for chain synchronization. +- Consensus engines for block verification. +- The runtime itself, in the case of pre-runtime digests. -```bash -brew install protobuf -``` +## Dispatchable -### Install Required Packages and Rust {: #install-required-packages-and-rust-mac-os } +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. -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`. +## Events -To install `openssl` and the Rust toolchain on macOS: +A means of recording that some particular [state](#state) transition happened. -1. Open the Terminal application. -2. Ensure you have an updated version of Homebrew by running the following command: +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. - ```bash - brew update - ``` +## Executor -3. Install the `openssl` package by running the following command: +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_. - ```bash - brew install openssl - ``` +- 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. -4. Download the `rustup` installation program and use it to install Rust by running the following command: +- 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 - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - ``` +## Existential Deposit -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 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. - ```bash - source ~/.cargo/env - ``` +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. -7. Configure the Rust toolchain to default to the latest stable version by running the following commands: +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}. - ```bash - rustup default stable - rustup update - rustup target add wasm32-unknown-unknown - rustup component add rust-src - ``` +## Extrinsic -8. Install `cmake` using the following command: +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. - ```bash - brew install cmake - ``` +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). -9. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). +For more technical details, see the [Polkadot spec](https://spec.polkadot.network/id-extrinsics){target=\_blank}. -## Install Dependencies: Linux +## Fork Choice Rule/Strategy -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). +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. -### Before You Begin {: #before-you-begin-linux } +## FRAME (Framework for Runtime Aggregation of Modularized Entities) -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: +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. -```bash -sudo apt install build-essential -``` +[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} -At a minimum, you need the following packages before you install Rust: +## Full Node -```text -clang curl git make -``` +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. -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`. +## Genesis Configuration -### Install Required Packages and Rust {: #install-required-packages-and-rust-linux } +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. -To install the Rust toolchain on Linux: +## GRANDPA -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: +A deterministic finality mechanism for blockchains that is implemented in the [Rust](https://www.rust-lang.org/){target=\_blank} programming language. - === "Ubuntu" +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}. - ```bash - sudo apt install --assume-yes git clang curl libssl-dev protobuf-compiler - ``` +## Header - === "Debian" +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. - ```sh - sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler - ``` +## Hybrid Consensus - === "Arch" +A blockchain consensus protocol that consists of independent or loosely coupled mechanisms for [block production](#block-author) and finality. - ```sh - pacman -Syu --needed --noconfirm curl git clang make protobuf - ``` +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). - === "Fedora" +## Inherent Transactions - ```sh - sudo dnf update - sudo dnf install clang curl git openssl-devel make protobuf-compiler - ``` +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. - === "OpenSUSE" +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. - ```sh - sudo zypper install clang curl git openssl-devel llvm-devel libudev-devel make protobuf - ``` +## JSON-RPC - 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 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. -4. Download the `rustup` installation program and use it to install Rust by running the following command: +For Polkadot SDK, this protocol is implemented through the [Parity JSON-RPC](https://github.com/paritytech/jsonrpc){target=\_blank} crate. - ```bash - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - ``` +## Keystore -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 - ``` +A subsystem for managing keys for the purpose of producing new blocks. -7. Verify your installation by running the following command: +## Kusama - ```bash - rustc --version - ``` +[Kusama](https://kusama.network/){target=\_blank} is a Polkadot SDK-based blockchain that implements a design similar to the [Polkadot](#polkadot) network. -8. Configure the Rust toolchain to default to the latest stable version by running the following commands: +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}. - ```bash - rustup default stable - rustup update - rustup target add wasm32-unknown-unknown - rustup component add rust-src - ``` +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. -9. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). +## libp2p -## Install Dependencies: Windows (WSL) +A peer-to-peer networking stack that allows the use of many transport mechanisms, including WebSockets (usable in a web browser). -In general, UNIX-based operating systems—like macOS or Linux—provide a better development environment for building Substrate-based blockchains. +Polkadot SDK uses the [Rust implementation](https://github.com/libp2p/rust-libp2p){target=\_blank} of the `libp2p` networking stack. -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. +## Light Client -### Before You Begin {: #before-you-begin-windows-wls } +A type of blockchain node that doesn't store the [chain state](#state) or produce blocks. -Before installing on Microsoft Windows, verify the following basic requirements: +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. -- 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. +## Metadata -### Set Up Windows Subsystem for Linux +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. -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. +## Nominated Proof of Stake (NPoS) -To prepare a development environment using WSL: +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. -1. Check your Windows version and build number to see if WSL is enabled by default. +## Oracle - 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. +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. - 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. +## Origin -2. Select **Windows PowerShell** or **Command Prompt** from the **Start** menu, right-click, then **Run as administrator**. +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}. -3. In the PowerShell or Command Prompt terminal, run the following command: +## Pallet - ```bash - wsl --install - ``` +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). - 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. +## Parachain - If you want to review the other Linux distributions available, run the following command: +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 - wsl --list --online - ``` +## Paseo -4. After the distribution is downloaded, close the terminal. +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. -5. Click the **Start** menu, select **Shut down or sign out**, then click **Restart** to restart the computer. +## Polkadot - 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 [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). - 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. +## Polkadot Cloud -### Install Required Packages and Rust {: #install-required-packages-and-rust-windows-wls } +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. -To install the Rust toolchain on WSL: +## Polkadot Hub -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: +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 - sudo apt update - ``` +## PolkaVM -5. Add the required packages for the Ubuntu distribution by running the following command: +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. - ```bash - sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler - ``` +## Relay Chain -6. Download the `rustup` installation program and use it to install Rust for the Ubuntu distribution by running the following command: +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. - ```bash - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - ``` +## Rococo -7. Follow the prompts displayed to proceed with a default installation. +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. -8. Update your current shell to include Cargo by running the following command: +## Runtime - ```bash - source ~/.cargo/env - ``` +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. -9. Verify your installation by running the following command: +## Slot - ```bash - rustc --version - ``` +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. -10. Configure the Rust toolchain to use the latest stable version as the default toolchain by running the following commands: +## Sovereign Account - ```bash - rustup default stable - rustup update - rustup target add wasm32-unknown-unknown - rustup component add rust-src - ``` +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. -11. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). +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. -## Build the Polkadot SDK +## SS58 Address Format -After installing all dependencies, you can now clone and compile the Polkadot SDK repository to verify your setup. +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 -### Clone the Polkadot SDK +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 -1. Clone the Polkadot SDK repository: +## State Transition Function (STF) - ```bash - git clone https://github.com/paritytech/polkadot-sdk.git - ``` +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). -2. Navigate into the project directory: +## Storage Item - ```bash - cd polkadot-sdk - ``` +[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. -### Compile the Polkadot SDK +## Substrate -Compile the entire Polkadot SDK repository to ensure your environment is properly configured: +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}. -```bash -cargo build --release --locked -``` +## Transaction -!!!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. +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}. -### Verify the Build +## Transaction Era -Once the build completes successfully, verify the installation by checking the compiled binaries: +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. -```bash -ls target/release -``` +## Trie (Patricia Merkle Tree) -You should see several binaries, including: +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. -- `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. +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. -Verify the Polkadot binary works by checking its version: +## Validator -```bash -./target/release/polkadot --version -``` +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. -This should display version information similar to: +## WebAssembly (Wasm) -```bash -polkadot 1.16.0-1234abcd567 -``` +An execution architecture that allows for the efficient, platform-neutral expression of +deterministic, machine-executable logic. -If you see the version output without errors, your development environment is correctly configured and ready for Polkadot SDK development! +[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. -## Optional: Run the Kitchensink Node +## Weight -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. +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. -!!!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 maximum block weight should be equivalent to one-third of the target block time with an allocation of one-third each for: -### Run the Kitchensink Node in Development Mode +- Block construction +- Network propagation +- Import and verification -From the `polkadot-sdk` root directory, start the kitchensink node in development mode: +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. -```bash -./target/release/substrate-node --dev -``` +## Westend -The `--dev` flag enables development mode, which: +Westend is a Parity-maintained, Polkadot SDK-based blockchain that serves as a test network for the [Polkadot](#polkadot) network. -- 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`. +Page Title: Install Polkadot SDK -### Interact with the Kitchensink Node +- 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. -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. +# Install Polkadot SDK -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. +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: -![](/images/parachains/install-polkadot-sdk/install-polkadot-sdk-1.webp) +- **Installing dependencies**: Setting up Rust, required system packages, and development tools. +- **Building the Polkadot SDK**: Cloning and compiling the Polkadot SDK repository. -Once connected, the interface updates its color scheme to indicate a successful connection to the local node. +Follow the appropriate section for your operating system to ensure all necessary tools are installed and configured properly. -![](/images/parachains/install-polkadot-sdk/install-polkadot-sdk-2.webp) +## Install Dependencies: macOS -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. +You can install Rust and set up a Substrate development environment on Apple macOS computers with Intel or Apple M1 processors. -To stop the node, press `Control-C` in the terminal. +### Before You Begin {: #before-you-begin-mac-os } -## Where to Go Next +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. -- __Get Started with Parachain Development__ +### 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. - Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. +To install Homebrew: - [:octicons-arrow-right-24: Get Started](/parachains/get-started/) - -
+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: -Page Title: Interact with the XCM Precompile + ```bash + brew --version + ``` -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles-xcm.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/precompiles/xcm/ -- Summary: Learn how to use the XCM precompile to send cross-chain messages, execute XCM instructions, and estimate costs from your smart contracts. + The command displays output similar to the following: -# XCM Precompile +
+ brew --version + Homebrew 4.3.15 +
-## Introduction +### Support for Apple Silicon -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. +Protobuf must be installed before the build process can begin. To install it, run the following command: -Located at the fixed address `0x00000000000000000000000000000000000a0000`, the XCM precompile offers three primary functions: +```bash +brew install protobuf +``` -- **`execute`**: For local XCM execution. -- **`send`**: For cross-chain message transmission. -- **`weighMessage`**: For cost estimation. +### Install Required Packages and Rust {: #install-required-packages-and-rust-mac-os } -This guide demonstrates how to interact with the XCM precompile through Solidity smart contracts using [Remix IDE](/smart-contracts/dev-environments/remix/get-started/){target=\_blank}. +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`. -!!!note - The XCM precompile provides the barebones XCM functionality. While it provides a lot of flexibility, it doesn't provide abstractions to hide away XCM details. These have to be built on top. +To install `openssl` and the Rust toolchain on macOS: -## Precompile Interface +1. Open the Terminal application. +2. Ensure you have an updated version of Homebrew by running the following command: -The XCM precompile implements the `IXcm` interface, which defines the structure for interacting with XCM functionality. The source code for the interface is as follows: + ```bash + brew update + ``` -```solidity title="IXcm.sol" -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +3. Install the `openssl` package by running the following command: -/// @dev The on-chain address of the XCM (Cross-Consensus Messaging) precompile. -address constant XCM_PRECOMPILE_ADDRESS = address(0xA0000); + ```bash + brew install openssl + ``` -/// @title XCM Precompile Interface -/// @notice A low-level interface for interacting with `pallet_xcm`. -/// It forwards calls directly to the corresponding dispatchable functions, -/// providing access to XCM execution and message passing. -/// @dev Documentation: -/// @dev - XCM: https://docs.polkadot.com/develop/interoperability -/// @dev - SCALE codec: https://docs.polkadot.com/polkadot-protocol/parachain-basics/data-encoding -/// @dev - Weights: https://docs.polkadot.com/polkadot-protocol/parachain-basics/blocks-transactions-fees/fees/#transactions-weights-and-fees -interface IXcm { - /// @notice Weight v2 used for measurement for an XCM execution - struct Weight { - /// @custom:property The computational time used to execute some logic based on reference hardware. - uint64 refTime; - /// @custom:property The size of the proof needed to execute some logic. - uint64 proofSize; - } +4. Download the `rustup` installation program and use it to install Rust by running the following command: - /// @notice Executes an XCM message locally on the current chain with the caller's origin. - /// @dev Internally calls `pallet_xcm::execute`. - /// @param message A SCALE-encoded Versioned XCM message. - /// @param weight The maximum allowed `Weight` for execution. - /// @dev Call @custom:function weighMessage(message) to ensure sufficient weight allocation. - function execute(bytes calldata message, Weight calldata weight) external; + ```bash + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + ``` - /// @notice Sends an XCM message to another parachain or consensus system. - /// @dev Internally calls `pallet_xcm::send`. - /// @param destination SCALE-encoded destination MultiLocation. - /// @param message SCALE-encoded Versioned XCM message. - function send(bytes calldata destination, bytes calldata message) external; +5. Follow the prompts displayed to proceed with a default installation. +6. Update your current shell to include Cargo by running the following command: - /// @notice Estimates the `Weight` required to execute a given XCM message. - /// @param message SCALE-encoded Versioned XCM message to analyze. - /// @return weight Struct containing estimated `refTime` and `proofSize`. - function weighMessage(bytes calldata message) external view returns (Weight memory weight); -} -``` + ```bash + source ~/.cargo/env + ``` -The interface defines a `Weight` struct that represents the computational cost of XCM operations. Weight has two components: +7. Configure the Rust toolchain to default to the latest stable version by running the following commands: -- **`refTime`**: Computational time on reference hardware. -- **`proofSize`**: The size of the proof required for execution. + ```bash + rustup default stable + rustup update + rustup target add wasm32-unknown-unknown + rustup component add rust-src + ``` -All XCM messages must be encoded using the [SCALE codec](/reference/parachains/data-encoding/#data-encoding){target=\_blank}, Polkadot's standard serialization format. +8. Install `cmake` using the following command: -For further information, check the [`precompiles/IXCM.sol`](https://github.com/paritytech/polkadot-sdk/blob/cb629d46ebf00aa65624013a61f9c69ebf02b0b4/polkadot/xcm/pallet-xcm/src/precompiles/IXcm.sol){target=\_blank} file present in `pallet-xcm`. + ```bash + brew install cmake + ``` -## Interact with the XCM Precompile +9. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). -To interact with the XCM precompile, you can use the precompile interface directly in [Remix IDE](/smart-contracts/dev-environments/remix/get-started/){target=\_blank}: +## Install Dependencies: Linux -1. Create a new file called `IXcm.sol` in Remix. -2. Copy and paste the `IXcm` interface code into the file. -3. Compile the interface by selecting the button or using **Ctrl +S** keys: +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). - ![](/images/smart-contracts/precompiles/xcm/xcm-01.webp) +### Before You Begin {: #before-you-begin-linux } -4. In the **Deploy & Run Transactions** tab, select the `IXcm` interface from the contract dropdown. -5. Enter the precompile address `0x00000000000000000000000000000000000a0000` in the **At Address** input field. -6. Select the **At Address** button to connect to the precompile. +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: - ![](/images/smart-contracts/precompiles/xcm/xcm-02.webp) +```bash +sudo apt install build-essential +``` -7. Once connected, you can use the Remix interface to interact with the XCM precompile's `execute`, `send`, and `weighMessage` functions. +At a minimum, you need the following packages before you install Rust: - ![](/images/smart-contracts/precompiles/xcm/xcm-03.webp) +```text +clang curl git make +``` -The main entrypoint of the precompile is the `execute` function. However, it's necessary to first call `weighMessage` to fill in the required parameters. +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`. -### Weigh a Message +### Install Required Packages and Rust {: #install-required-packages-and-rust-linux } -The `weighMessage` function estimates the computational cost required to execute an XCM message. This estimate is crucial for understanding the resources needed before actually executing or sending a message. +To install the Rust toolchain on Linux: -To test this functionality in Remix, you can call `callWeighMessage` with a SCALE-encoded XCM message. For example, for testing, you can use the following encoded XCM message: +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: -```text title="encoded-xcm-message-example" -0x050c000401000003008c86471301000003008c8647000d010101000000010100368e8759910dab756d344995f1d3c79374ca8f70066d3a709e48029f6bf0ee7e -``` + === "Ubuntu" -![](/images/smart-contracts/precompiles/xcm/xcm-04.webp) + ```bash + sudo apt install --assume-yes git clang curl libssl-dev protobuf-compiler + ``` -This encoded message represents a sequence of XCM instructions: + === "Debian" -- **[Withdraw Asset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#withdrawasset){target=\_blank}**: This instruction removes assets from the local chain's sovereign account or the caller's account, making them available for use in subsequent XCM instructions. -- **[Buy Execution](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#buyexecution){target=\_blank}**: This instruction purchases execution time on the destination chain using the withdrawn assets, ensuring the message can be processed. -- **[Deposit Asset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#depositasset){target=\_blank}**: This instruction deposits the remaining assets into a specified account on the destination chain after execution costs have been deducted. + ```sh + sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler + ``` -This encoded message is provided as an example. You can craft your own XCM message tailored to your specific use case as needed. + === "Arch" -The function returns a `Weight` struct containing `refTime` and `proofSize` values, which indicate the estimated computational cost of executing this message. If successful, after calling the `callWeighMessage` function, you should see the `refTime` and `proofSize` of the message: + ```sh + pacman -Syu --needed --noconfirm curl git clang make protobuf + ``` -![](/images/smart-contracts/precompiles/xcm/xcm-05.webp) + === "Fedora" -!!!note - You can find many more examples of XCMs in this [gist](https://gist.github.com/franciscoaguirre/a6dea0c55e81faba65bedf700033a1a2){target=\_blank}, which connects to the Polkadot Hub TestNet. + ```sh + sudo dnf update + sudo dnf install clang curl git openssl-devel make protobuf-compiler + ``` -### Execute a Message + === "OpenSUSE" -The `execute` function runs an XCM message locally using the caller's origin. -This function is the main entrypoint to cross-chain interactions. + ```sh + sudo zypper install clang curl git openssl-devel llvm-devel libudev-devel make protobuf + ``` -Follow these steps to execute a message: + 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. -1. Call `weighMessage` with your message to get the required weight. -2. Pass the same message bytes and the weight obtained from the previous step to `execute`. -For example, using the same message from the weighing example, you would call `execute` with: +4. Download the `rustup` installation program and use it to install Rust by running the following command: - - **`message`**: The encoded XCM message bytes. - - **`weight`**: The `Weight` struct returned from `weighMessage`. + ```bash + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + ``` - You can use the [papi console](https://dev.papi.how/extrinsics#networkId=localhost&endpoint=wss%3A%2F%2Ftestnet-passet-hub.polkadot.io&data=0x1f03050c000401000003008c86471301000003008c8647000d010101000000010100368e8759910dab756d344995f1d3c79374ca8f70066d3a709e48029f6bf0ee7e0750c61e2901daad0600){target=\_blank} to examine the complete extrinsic structure for this operation. +5. Follow the prompts displayed to proceed with a default installation. +6. Update your current shell to include Cargo by running the following command: -3. On Remix, click on the **Transact** button to execute the XCM message: - - ![](/images/smart-contracts/precompiles/xcm/xcm-06.webp) + ```bash + source $HOME/.cargo/env + ``` - If successful, you will see the following output in the Remix terminal: +7. Verify your installation by running the following command: - ![](/images/smart-contracts/precompiles/xcm/xcm-07.webp) + ```bash + rustc --version + ``` -Additionally, you can verify that the execution of this specific message was successful by checking that the beneficiary account associated with the XCM message has received the funds accordingly. +8. Configure the Rust toolchain to default to the latest stable version by running the following commands: -### Send a Message + ```bash + rustup default stable + rustup update + rustup target add wasm32-unknown-unknown + rustup component add rust-src + ``` -While most cross-chain operations can be performed via `execute`, `send` is sometimes necessary, for example, when opening HRMP channels. +9. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). -To send a message: +## Install Dependencies: Windows (WSL) -1. Prepare your destination location encoded in XCM format. -2. Prepare your XCM message (similar to the execute example). -3. Call `send` with both parameters. +In general, UNIX-based operating systems—like macOS or Linux—provide a better development environment for building Substrate-based blockchains. -The destination parameter must be encoded according to XCM's location format, specifying the target parachain or consensus system. The message parameter contains the XCM instructions to be executed on the destination chain. +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. -Unlike `execute`, the `send` function doesn't require a weight parameter since the destination chain will handle execution costs according to its fee structure. +### Before You Begin {: #before-you-begin-windows-wls } -## Cross Contract Calls +Before installing on Microsoft Windows, verify the following basic requirements: -Beyond direct interaction and wrapper contracts, you can integrate XCM functionality directly into your existing smart contracts by inheriting from or importing the `IXcm` interface. This approach enables you to embed cross-chain capabilities into your application logic seamlessly. +- 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. -Whether you're building DeFi protocols, governance systems, or any application requiring cross-chain coordination, you can incorporate XCM calls directly within your contract's functions. +### Set Up Windows Subsystem for Linux -## Conclusion +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. -The XCM precompile provides a simple yet powerful interface for cross-chain interactions within the Polkadot ecosystem and beyond. -By building and executing XCM programs, developers can build cross-chain applications that leverage the full potential of Polkadot's interoperability features. +To prepare a development environment using WSL: -## Next Steps +1. Check your Windows version and build number to see if WSL is enabled by default. -Head to the Polkadot Hub TestNet and start playing around with the precompile using [Hardhat](/smart-contracts/dev-environments/hardhat/get-started/){target=\_blank} or [Foundry](/smart-contracts/dev-environments/foundry/get-started/){target=\_blank}. + 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. -You can use PAPI to build XCM programs and test them with Chopsticks. + 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: -Page Title: Interoperability + ```bash + wsl --install + ``` -- 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. + 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. -# Interoperability + If you want to review the other Linux distributions available, run the following command: -## Introduction + ```bash + wsl --list --online + ``` -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. +4. After the distribution is downloaded, close the terminal. -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. +5. Click the **Start** menu, select **Shut down or sign out**, then click **Restart** to restart the computer. -## Why Interoperability Matters + 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 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. + 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. -Interoperability solves this problem by enabling blockchains to: +### Install Required Packages and Rust {: #install-required-packages-and-rust-windows-wls } -- **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. +To install the Rust toolchain on WSL: -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. +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: -## Key Mechanisms for Interoperability + ```bash + sudo apt update + ``` -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. +5. Add the required packages for the Ubuntu distribution by running the following command: -### Cross-Consensus Messaging (XCM): The Backbone of Communication + ```bash + sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler + ``` -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. +6. Download the `rustup` installation program and use it to install Rust for the Ubuntu distribution by running the following command: -Through XCM, decentralized applications can: + ```bash + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + ``` -- 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. +7. Follow the prompts displayed to proceed with a default installation. -For further information about XCM, check the [Introduction to XCM](/parachains/interoperability/get-started/){target=\_blank} article. +8. Update your current shell to include Cargo by running the following command: -### Bridges: Connecting External Networks + ```bash + source ~/.cargo/env + ``` -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. +9. Verify your installation by running the following command: -With bridges, developers and users gain the ability to: + ```bash + rustc --version + ``` -- 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. +10. Configure the Rust toolchain to use the latest stable version as the default toolchain by running the following commands: -For more information about bridges in the Polkadot ecosystem, see the [Bridge Hub](/reference/polkadot-hub/bridging/){target=\_blank} guide. + ```bash + rustup default stable + rustup update + rustup target add wasm32-unknown-unknown + rustup component add rust-src + ``` -## The Polkadot Advantage +11. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). -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: +## Build the Polkadot SDK -- **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. +After installing all dependencies, you can now clone and compile the Polkadot SDK repository to verify your setup. -## Looking Ahead +### Clone the Polkadot SDK -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. +1. Clone the Polkadot SDK repository: + ```bash + git clone https://github.com/paritytech/polkadot-sdk.git + ``` ---- +2. Navigate into the project directory: -Page Title: Introduction to XCM + ```bash + cd polkadot-sdk + ``` -- 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. +### Compile the Polkadot SDK -# Introduction to XCM +Compile the entire Polkadot SDK repository to ensure your environment is properly configured: -## Introduction +```bash +cargo build --release --locked +``` -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. +!!!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. -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. +### Verify the Build -## Messaging Format +Once the build completes successfully, verify the installation by checking the compiled binaries: -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. +```bash +ls target/release +``` -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. +You should see several binaries, including: -## The Four Principles of XCM +- `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 adheres to four guiding principles that ensure robust and reliable communication across consensus systems: +Verify the Polkadot binary works by checking its version: -- **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. +```bash +./target/release/polkadot --version +``` -These principles guarantee that XCM provides a reliable framework for cross-chain communication, even in complex environments. +This should display version information similar to: -## The XCM Tech Stack +```bash +polkadot 1.16.0-1234abcd567 +``` -![Diagram of the XCM tech stack](/images/parachains/interoperability/get-started/intro-to-xcm-01.webp) +If you see the version output without errors, your development environment is correctly configured and ready for Polkadot SDK development! -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. +## Optional: Run the Kitchensink Node -## Core Functionalities of XCM +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. -XCM enhances cross-consensus communication by introducing several powerful features: +!!!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. -- **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. +### Run the Kitchensink Node in Development Mode -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. +From the `polkadot-sdk` root directory, start the kitchensink node in development mode: -## XCM Example +```bash +./target/release/substrate-node --dev +``` -The following is a simplified XCM message demonstrating a token transfer from Alice to Bob on the same chain (ParaA). +The `--dev` flag enables development mode, which: -```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() - } -]); -``` +- 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. -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. +You should see log output indicating the node is running and producing blocks, with increasing block numbers after `finalized`. - ```rust - WithdrawAsset((Here, amount).into()), - ``` +### Interact with the Kitchensink Node - - **`Here`**: The native parachain token. - - **`amount`**: The number of tokens that are transferred. +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. - 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. +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. -- **[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. +![](/images/parachains/install-polkadot-sdk/install-polkadot-sdk-1.webp) - ```rust - BuyExecution { - fees: (Here, amount).into(), - weight_limit: WeightLimit::Unlimited - }, - ``` +Once connected, the interface updates its color scheme to indicate a successful connection to the local node. - - **`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. +![](/images/parachains/install-polkadot-sdk/install-polkadot-sdk-2.webp) -- **[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. +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. - ```rust - DepositAsset { - assets: All.into(), - beneficiary: MultiLocation { - parents: 0, - interior: Junction::AccountId32 { - network: None, - id: BOB.clone().into() - }.into(), - }.into() - } - ``` +To stop the node, press `Control-C` in the terminal. - - **`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}. +## Where to Go Next -## Overview +
-XCM revolutionizes cross-chain communication by enabling use cases such as: +- __Get Started with Parachain Development__ -- 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}. + 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: JSON-RPC APIs +Page Title: Interact with the XCM Precompile -- 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. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles-xcm.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/precompiles/xcm/ +- Summary: Learn how to use the XCM precompile to send cross-chain messages, execute XCM instructions, and estimate costs from your smart contracts. -# JSON-RPC APIs +# XCM Precompile -!!! 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. +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. -This guide uses the Polkadot Hub TestNet endpoint: +Located at the fixed address `0x00000000000000000000000000000000000a0000`, the XCM precompile offers three primary functions: -```text -https://testnet-passet-hub-eth-rpc.polkadot.io -``` - -## Available Methods - -### eth_accounts +- **`execute`**: For local XCM execution. +- **`send`**: For cross-chain message transmission. +- **`weighMessage`**: For cost estimation. -Returns a list of addresses owned by the client. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_accounts){target=\_blank}. +This guide demonstrates how to interact with the XCM precompile through Solidity smart contracts using [Remix IDE](/smart-contracts/dev-environments/remix/get-started/){target=\_blank}. -**Parameters**: +!!!note + The XCM precompile provides the barebones XCM functionality. While it provides a lot of flexibility, it doesn't provide abstractions to hide away XCM details. These have to be built on top. -None. +## Precompile Interface -**Example**: +The XCM precompile implements the `IXcm` interface, which defines the structure for interacting with XCM functionality. The source code for the interface is as follows: -```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 -}' -``` +```solidity title="IXcm.sol" +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; ---- +/// @dev The on-chain address of the XCM (Cross-Consensus Messaging) precompile. +address constant XCM_PRECOMPILE_ADDRESS = address(0xA0000); -### eth_blockNumber +/// @title XCM Precompile Interface +/// @notice A low-level interface for interacting with `pallet_xcm`. +/// It forwards calls directly to the corresponding dispatchable functions, +/// providing access to XCM execution and message passing. +/// @dev Documentation: +/// @dev - XCM: https://docs.polkadot.com/develop/interoperability +/// @dev - SCALE codec: https://docs.polkadot.com/polkadot-protocol/parachain-basics/data-encoding +/// @dev - Weights: https://docs.polkadot.com/polkadot-protocol/parachain-basics/blocks-transactions-fees/fees/#transactions-weights-and-fees +interface IXcm { + /// @notice Weight v2 used for measurement for an XCM execution + struct Weight { + /// @custom:property The computational time used to execute some logic based on reference hardware. + uint64 refTime; + /// @custom:property The size of the proof needed to execute some logic. + uint64 proofSize; + } -Returns the number of the most recent block. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_blocknumber){target=\_blank}. + /// @notice Executes an XCM message locally on the current chain with the caller's origin. + /// @dev Internally calls `pallet_xcm::execute`. + /// @param message A SCALE-encoded Versioned XCM message. + /// @param weight The maximum allowed `Weight` for execution. + /// @dev Call @custom:function weighMessage(message) to ensure sufficient weight allocation. + function execute(bytes calldata message, Weight calldata weight) external; -**Parameters**: + /// @notice Sends an XCM message to another parachain or consensus system. + /// @dev Internally calls `pallet_xcm::send`. + /// @param destination SCALE-encoded destination MultiLocation. + /// @param message SCALE-encoded Versioned XCM message. + function send(bytes calldata destination, bytes calldata message) external; -None. + /// @notice Estimates the `Weight` required to execute a given XCM message. + /// @param message SCALE-encoded Versioned XCM message to analyze. + /// @return weight Struct containing estimated `refTime` and `proofSize`. + function weighMessage(bytes calldata message) external view returns (Weight memory weight); +} +``` -**Example**: +The interface defines a `Weight` struct that represents the computational cost of XCM operations. Weight has two components: -```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 -}' -``` +- **`refTime`**: Computational time on reference hardware. +- **`proofSize`**: The size of the proof required for execution. ---- +All XCM messages must be encoded using the [SCALE codec](/reference/parachains/data-encoding/#data-encoding){target=\_blank}, Polkadot's standard serialization format. -### eth_call +For further information, check the [`precompiles/IXCM.sol`](https://github.com/paritytech/polkadot-sdk/blob/cb629d46ebf00aa65624013a61f9c69ebf02b0b4/polkadot/xcm/pallet-xcm/src/precompiles/IXcm.sol){target=\_blank} file present in `pallet-xcm`. -Executes a new message call immediately without creating a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_call){target=\_blank}. +## Interact with the XCM Precompile -**Parameters**: +To interact with the XCM precompile, you can use the precompile interface directly in [Remix IDE](/smart-contracts/dev-environments/remix/get-started/){target=\_blank}: -- **`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}. +1. Create a new file called `IXcm.sol` in Remix. +2. Copy and paste the `IXcm` interface code into the file. +3. Compile the interface by selecting the button or using **Ctrl +S** keys: -**Example**: + ![](/images/smart-contracts/precompiles/xcm/xcm-01.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 -}' -``` +4. In the **Deploy & Run Transactions** tab, select the `IXcm` interface from the contract dropdown. +5. Enter the precompile address `0x00000000000000000000000000000000000a0000` in the **At Address** input field. +6. Select the **At Address** button to connect to the precompile. -Ensure to replace the `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper values. + ![](/images/smart-contracts/precompiles/xcm/xcm-02.webp) ---- +7. Once connected, you can use the Remix interface to interact with the XCM precompile's `execute`, `send`, and `weighMessage` functions. -### eth_chainId + ![](/images/smart-contracts/precompiles/xcm/xcm-03.webp) -Returns the chain ID used for signing transactions. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_chainid){target=\_blank}. +The main entrypoint of the precompile is the `execute` function. However, it's necessary to first call `weighMessage` to fill in the required parameters. -**Parameters**: +### Weigh a Message -None. +The `weighMessage` function estimates the computational cost required to execute an XCM message. This estimate is crucial for understanding the resources needed before actually executing or sending a message. -**Example**: +To test this functionality in Remix, you can call `callWeighMessage` with a SCALE-encoded XCM message. For example, for testing, you can use the following encoded XCM message: -```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 -}' +```text title="encoded-xcm-message-example" +0x050c000401000003008c86471301000003008c8647000d010101000000010100368e8759910dab756d344995f1d3c79374ca8f70066d3a709e48029f6bf0ee7e ``` ---- +![](/images/smart-contracts/precompiles/xcm/xcm-04.webp) -### eth_estimateGas +This encoded message represents a sequence of XCM instructions: -Estimates gas required for a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_estimategas){target=\_blank}. +- **[Withdraw Asset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#withdrawasset){target=\_blank}**: This instruction removes assets from the local chain's sovereign account or the caller's account, making them available for use in subsequent XCM instructions. +- **[Buy Execution](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#buyexecution){target=\_blank}**: This instruction purchases execution time on the destination chain using the withdrawn assets, ensuring the message can be processed. +- **[Deposit Asset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#depositasset){target=\_blank}**: This instruction deposits the remaining assets into a specified account on the destination chain after execution costs have been deducted. -**Parameters**: +This encoded message is provided as an example. You can craft your own XCM message tailored to your specific use case as needed. -- **`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 function returns a `Weight` struct containing `refTime` and `proofSize` values, which indicate the estimated computational cost of executing this message. If successful, after calling the `callWeighMessage` function, you should see the `refTime` and `proofSize` of the message: -**Example**: +![](/images/smart-contracts/precompiles/xcm/xcm-05.webp) -```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 -}' -``` +!!!note + You can find many more examples of XCMs in this [gist](https://gist.github.com/franciscoaguirre/a6dea0c55e81faba65bedf700033a1a2){target=\_blank}, which connects to the Polkadot Hub TestNet. -Ensure to replace the `INSERT_RECIPIENT_ADDRESS` and `INSERT_ENCODED_CALL` with the proper values. +### Execute a Message ---- +The `execute` function runs an XCM message locally using the caller's origin. +This function is the main entrypoint to cross-chain interactions. -### eth_gasPrice +Follow these steps to execute a message: -Returns the current gas price in Wei. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gasprice){target=\_blank}. +1. Call `weighMessage` with your message to get the required weight. +2. Pass the same message bytes and the weight obtained from the previous step to `execute`. +For example, using the same message from the weighing example, you would call `execute` with: -**Parameters**: + - **`message`**: The encoded XCM message bytes. + - **`weight`**: The `Weight` struct returned from `weighMessage`. -None. + You can use the [papi console](https://dev.papi.how/extrinsics#networkId=localhost&endpoint=wss%3A%2F%2Ftestnet-passet-hub.polkadot.io&data=0x1f03050c000401000003008c86471301000003008c8647000d010101000000010100368e8759910dab756d344995f1d3c79374ca8f70066d3a709e48029f6bf0ee7e0750c61e2901daad0600){target=\_blank} to examine the complete extrinsic structure for this operation. -**Example**: +3. On Remix, click on the **Transact** button to execute the XCM message: + + ![](/images/smart-contracts/precompiles/xcm/xcm-06.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 -}' -``` + If successful, you will see the following output in the Remix terminal: ---- + ![](/images/smart-contracts/precompiles/xcm/xcm-07.webp) -### eth_getBalance +Additionally, you can verify that the execution of this specific message was successful by checking that the beneficiary account associated with the XCM message has received the funds accordingly. -Returns the balance of a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getbalance){target=\_blank}. +### Send a Message -**Parameters**: +While most cross-chain operations can be performed via `execute`, `send` is sometimes necessary, for example, when opening HRMP channels. -- **`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}. +To send a message: -**Example**: +1. Prepare your destination location encoded in XCM format. +2. Prepare your XCM message (similar to the execute example). +3. Call `send` with both parameters. -```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 destination parameter must be encoded according to XCM's location format, specifying the target parachain or consensus system. The message parameter contains the XCM instructions to be executed on the destination chain. -Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. +Unlike `execute`, the `send` function doesn't require a weight parameter since the destination chain will handle execution costs according to its fee structure. ---- +## Cross Contract Calls -### eth_getBlockByHash +Beyond direct interaction and wrapper contracts, you can integrate XCM functionality directly into your existing smart contracts by inheriting from or importing the `IXcm` interface. This approach enables you to embed cross-chain capabilities into your application logic seamlessly. -Returns information about a block by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbyhash){target=\_blank}. +Whether you're building DeFi protocols, governance systems, or any application requiring cross-chain coordination, you can incorporate XCM calls directly within your contract's functions. -**Parameters**: +## Conclusion -- **`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. +The XCM precompile provides a simple yet powerful interface for cross-chain interactions within the Polkadot ecosystem and beyond. +By building and executing XCM programs, developers can build cross-chain applications that leverage the full potential of Polkadot's interoperability features. -**Example**: +## Next Steps -```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 -}' -``` +Head to the Polkadot Hub TestNet and start playing around with the precompile using [Hardhat](/smart-contracts/dev-environments/hardhat/get-started/){target=\_blank} or [Foundry](/smart-contracts/dev-environments/foundry/get-started/){target=\_blank}. + +You can use PAPI to build XCM programs and test them with Chopsticks. -Ensure to replace the `INSERT_BLOCK_HASH` and `INSERT_BOOLEAN` with the proper values. --- -### eth_getBlockByNumber +Page Title: Interoperability -Returns information about a block by its number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbynumber){target=\_blank}. +- 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. -**Parameters**: +# Interoperability -- **`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. +## Introduction -**Example**: +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. -```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 -}' -``` +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. -Ensure to replace the `INSERT_BLOCK_VALUE` and `INSERT_BOOLEAN` with the proper values. +## 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. -### eth_getBlockTransactionCountByNumber +Interoperability solves this problem by enabling blockchains to: -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}. +- **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. -**Parameters**: +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. -- **`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}. +## Key Mechanisms for Interoperability -**Example**: +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. -```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 -}' -``` +### Cross-Consensus Messaging (XCM): The Backbone of Communication -Ensure to replace the `INSERT_BLOCK_VALUE` with the proper values. +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_getBlockTransactionCountByHash +- 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 transactions in a block from a block hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbyhash){target=\_blank}. +For further information about XCM, check the [Introduction to XCM](/parachains/interoperability/get-started/){target=\_blank} article. -**Parameters**: +### Bridges: Connecting External Networks -- **`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. +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_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 -}' -``` +- 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. -Ensure to replace the `INSERT_BLOCK_HASH` with the proper values. +For more information about bridges in the Polkadot ecosystem, see the [Bridge Hub](/reference/polkadot-hub/bridging/){target=\_blank} guide. ---- +## The Polkadot Advantage -### eth_getCode +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: -Returns the code at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getcode){target=\_blank}. +- **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. -**Parameters**: +## Looking Ahead -- **`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’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. -**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. +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. -### eth_getLogs +# Introduction to XCM -Returns an array of all logs matching a given filter object. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getlogs){target=\_blank}. +## Introduction -**Parameters**: +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. -- **`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. +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. -**Example**: +## Messaging Format -```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 -}' -``` +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. -### eth_getStorageAt +## The Four Principles of XCM -Returns the value from a storage position at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getstorageat){target=\_blank}. +XCM adheres to four guiding principles that ensure robust and reliable communication across consensus systems: -**Parameters**: +- **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. -- **`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). +These principles guarantee that XCM provides a reliable framework for cross-chain communication, even in complex environments. -**Example**: +## The XCM Tech Stack -```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 -}' -``` +![Diagram of the XCM tech stack](/images/parachains/interoperability/get-started/intro-to-xcm-01.webp) -Ensure to replace the `INSERT_ADDRESS`, `INSERT_STORAGE_KEY`, and `INSERT_BLOCK_VALUE` with the proper values. +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 -### eth_getTransactionCount +XCM enhances cross-consensus communication by introducing several powerful features: -Returns the number of transactions sent from an address (nonce). [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactioncount){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. -**Parameters**: +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. -- **`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). +## XCM Example -**Example**: +The following is a simplified XCM message demonstrating a token transfer from Alice to Bob on the same chain (ParaA). -```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 -}' +```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() + } +]); ``` -Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. +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. -### eth_getTransactionByHash + ```rust + WithdrawAsset((Here, amount).into()), + ``` -Returns information about a transaction by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyhash){target=\_blank}. + - **`Here`**: The native parachain token. + - **`amount`**: The number of tokens that are transferred. -**Parameters**: + 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. -- **`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. +- **[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. -**Example**: + ```rust + BuyExecution { + fees: (Here, amount).into(), + weight_limit: WeightLimit::Unlimited + }, + ``` -```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 -}' -``` + - **`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}. -Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper values. --- -### eth_getTransactionByBlockNumberAndIndex +Page Title: JSON-RPC APIs -Returns information about a transaction by block number and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblocknumberandindex){target=\_blank}. +- 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. -**Parameters**: +# JSON-RPC APIs -- **`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. +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. +## Introduction -**Example**: +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. -```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 -}' -``` +This guide uses the Polkadot Hub TestNet endpoint: -Ensure to replace the `INSERT_BLOCK_VALUE` and `INSERT_TRANSACTION_INDEX` with the proper values. +```text +https://testnet-passet-hub-eth-rpc.polkadot.io +``` ---- +## Available Methods -### eth_getTransactionByBlockHashAndIndex +### eth_accounts -Returns information about a transaction by block hash and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblockhashandindex){target=\_blank}. +Returns a list of addresses owned by the client. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_accounts){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. +None. **Example**: -```bash title="eth_getTransactionByBlockHashAndIndex" +```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_getTransactionByBlockHashAndIndex", - "params":["INSERT_BLOCK_HASH", "INSERT_TRANSACTION_INDEX"], + "method":"eth_accounts", + "params":[], "id":1 }' ``` -Ensure to replace the `INSERT_BLOCK_HASH` and `INSERT_TRANSACTION_INDEX` with the proper values. - --- -### eth_getTransactionReceipt +### eth_blockNumber -Returns the receipt of a transaction by transaction hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionreceipt){target=\_blank}. +Returns the number of the most recent block. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_blocknumber){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. +None. **Example**: -```bash title="eth_getTransactionReceipt" +```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_getTransactionReceipt", - "params":["INSERT_TRANSACTION_HASH"], + "method":"eth_blockNumber", + "params":[], "id":1 }' ``` -Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper values. - --- -### eth_maxPriorityFeePerGas +### eth_call -Returns an estimate of the current priority fee per gas, in Wei, to be included in a block. +Executes a new message call immediately without creating a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_call){target=\_blank}. **Parameters**: -None. +- **`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_maxPriorityFeePerGas" +```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_maxPriorityFeePerGas", - "params":[], + "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_sendRawTransaction +### eth_chainId -Submits a raw transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendrawtransaction){target=\_blank}. +Returns the chain ID used for signing transactions. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_chainid){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. +None. **Example**: -```bash title="eth_sendRawTransaction" +```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_sendRawTransaction", - "params":["INSERT_CALL_DATA"], + "method":"eth_chainId", + "params":[], "id":1 }' ``` -Ensure to replace the `INSERT_CALL_DATA` with the proper values. - --- -### eth_sendTransaction +### eth_estimateGas -Creates and sends a new transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendtransaction){target=\_blank}. +Estimates gas required for a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_estimategas){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. +- **`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_sendTransaction" +```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_sendTransaction", + "method":"eth_estimateGas", "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" + "data": "INSERT_ENCODED_FUNCTION_CALL" }], "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. +Ensure to replace the `INSERT_RECIPIENT_ADDRESS` and `INSERT_ENCODED_CALL` with the proper values. --- -### eth_syncing +### eth_gasPrice -Returns an object with syncing data or `false` if not syncing. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_syncing){target=\_blank}. +Returns the current gas price in Wei. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gasprice){target=\_blank}. **Parameters**: @@ -5872,12 +6036,12 @@ None. **Example**: -```bash title="eth_syncing" +```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_syncing", + "method":"eth_gasPrice", "params":[], "id":1 }' @@ -5885,4339 +6049,4305 @@ curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --- -### net_listening +### eth_getBalance -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}. +Returns the balance of a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getbalance){target=\_blank}. **Parameters**: -None. +- **`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="net_listening" +```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":"net_listening", - "params":[], + "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. + --- -### net_peerCount +### eth_getBlockByHash -Returns the number of peers currently connected to the client. +Returns information about a block by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbyhash){target=\_blank}. **Parameters**: -None. +- **`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="net_peerCount" +```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":"net_peerCount", - "params":[], + "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. + --- -### net_version +### eth_getBlockByNumber -Returns the current network ID as a string. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_version){target=\_blank}. +Returns information about a block by its number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbynumber){target=\_blank}. **Parameters**: -None. +- **`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="net_version" +```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":"net_version", - "params":[], + "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. + --- -### system_health +### eth_getBlockTransactionCountByNumber -Returns information about the health of the system. +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**: -None. +- **`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="system_health" +```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":"system_health", - "params":[], + "method":"eth_getBlockTransactionCountByNumber", + "params":["INSERT_BLOCK_VALUE"], "id":1 }' ``` +Ensure to replace the `INSERT_BLOCK_VALUE` with the proper values. + --- -### web3_clientVersion +### eth_getBlockTransactionCountByHash -Returns the current client version. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#web3_clientversion){target=\_blank}. +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**: -None. +- **`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="web3_clientVersion" +```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":"web3_clientVersion", - "params":[], + "method":"eth_getBlockTransactionCountByHash", + "params":["INSERT_BLOCK_HASH"], "id":1 }' ``` +Ensure to replace the `INSERT_BLOCK_HASH` with the proper values. + --- -### debug_traceBlockByNumber +### eth_getCode -Traces a block's execution by its number and returns a detailed execution trace for each transaction. +Returns the code at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getcode){target=\_blank}. **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. +- **`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="debug_traceBlockByNumber" +```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":"debug_traceBlockByNumber", - "params":["INSERT_BLOCK_VALUE", {"tracer": "callTracer"}], + "method":"eth_getCode", + "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], "id":1 }' ``` -Ensure to replace `INSERT_BLOCK_VALUE` with a proper block number if needed. +Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. --- -### debug_traceTransaction +### eth_getLogs -Traces the execution of a single transaction by its hash and returns a detailed execution trace. +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**: -- **`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"`). +- **`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="debug_traceTransaction" +```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":"debug_traceTransaction", - "params":["INSERT_TRANSACTION_HASH", {"tracer": "callTracer"}], + "method":"eth_getLogs", + "params":[{ + "fromBlock": "latest", + "toBlock": "latest" + }], "id":1 }' ``` -Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper value. - --- -### debug_traceCall +### eth_getStorageAt -Executes a new message call and returns a detailed execution trace without creating a transaction on the blockchain. +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**: -- **`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"`). +- **`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="debug_traceCall" +```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":"debug_traceCall", - "params":[{ - "from": "INSERT_SENDER_ADDRESS", - "to": "INSERT_RECIPIENT_ADDRESS", - "data": "INSERT_ENCODED_CALL" - }, "INSERT_BLOCK_VALUE", {"tracer": "callTracer"}], + "method":"eth_getStorageAt", + "params":["INSERT_ADDRESS", "INSERT_STORAGE_KEY", "INSERT_BLOCK_VALUE"], "id":1 }' ``` -Ensure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper value. +Ensure to replace the `INSERT_ADDRESS`, `INSERT_STORAGE_KEY`, and `INSERT_BLOCK_VALUE` with the proper values. --- -## Response Format +### eth_getTransactionCount -All responses follow the standard JSON-RPC 2.0 format: +Returns the number of transactions sent from an address (nonce). [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactioncount){target=\_blank}. -```json -{ - "jsonrpc": "2.0", - "id": 1, - "result": ... // The return value varies by method -} -``` +**Parameters**: -## Error Handling +- **`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). -If an error occurs, the response will include an error object: +**Example**: -```json -{ - "jsonrpc": "2.0", - "id": 1, - "error": { - "code": -32000, - "message": "Error message here" - } -} +```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. --- -Page Title: Local Development Node - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-local-dev-node.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/dev-environments/local-dev-node/ -- Summary: Follow this step-by-step guide to install a Revive Dev node and ETH-RPC adapter for smart contract development in a local environment. +### eth_getTransactionByHash -# Local Development Node +Returns information about a transaction by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyhash){target=\_blank}. -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction +**Parameters**: -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. +- **`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. -By the end of this guide, you'll have: +**Example**: -- A running node with smart contract support. -- An ETH-RPC adapter for Ethereum-compatible tooling integration accessible at `http://localhost:8545`. +```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 +}' +``` -## Prerequisites +Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper values. -Before getting started, ensure you have done the following: +--- -- 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. +### eth_getTransactionByBlockNumberAndIndex -## Install the Revive Dev Node and ETH-RPC Adapter +Returns information about a transaction by block number and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblocknumberandindex){target=\_blank}. -The 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: +**Parameters**: -```bash -git clone https://github.com/paritytech/polkadot-sdk.git -cd polkadot-sdk -git checkout 8e2b6f742a38bb13688e12abacded0aab2dbbb23 -``` +- **`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. -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: +**Example**: -```bash -cargo build -p revive-dev-node --bin revive-dev-node --release -cargo build -p pallet-revive-eth-rpc --bin eth-rpc --release +```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 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: - -- **Revive Dev node path**: `polkadot-sdk/target/release/revive-dev-node` -- **ETH-RPC adapter path**: `polkadot-sdk/target/release/eth-rpc` - -## Run the Local Node +Ensure to replace the `INSERT_BLOCK_VALUE` and `INSERT_TRANSACTION_INDEX` with the proper values. -With the binaries compiled, you can now start your local development environment. The setup requires running two processes. +--- -Start 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: +### eth_getTransactionByBlockHashAndIndex -```bash -./target/release/revive-dev-node --dev -``` +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 node will begin producing blocks immediately and display initialization logs: +**Parameters**: -
- ./target/release/revive-dev-node --dev -
- 2025-05-29 10:42:35 Substrate Node - 2025-05-29 10:42:35 ✌️ version 3.0.0-dev-38b7581fc04 - 2025-05-29 10:42:35 ❤️ by Parity Technologies <admin@parity.io>, 2017-2025 - 2025-05-29 10:42:35 📋 Chain specification: Development - 2025-05-29 10:42:35 🏷 Node name: annoyed-aunt-3163 - 2025-05-29 10:42:35 👤 Role: AUTHORITY - 2025-05-29 10:42:35 💾 Database: RocksDb at /var/folders/x0/xl_kjddj3ql3bx7752yr09hc0000gn/T/substrate2P85EF/chains/dev/db/full - 2025-05-29 10:42:40 🔨 Initializing Genesis block/state (state: 0xfc05…482e, header-hash: 0x1ae1…b8b4) - 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 } - 2025-05-29 10:42:40 👴 Loading GRANDPA authority set from genesis on what appears to be first startup. - 2025-05-29 10:42:40 👶 Creating empty BABE epoch changes on what appears to be first startup. - 2025-05-29 10:42:40 Using default protocol ID "sup" because none is configured in the chain specs - 2025-05-29 10:42:40 🏷 Local node identity is: 12D3KooWAH8fgJv3hce7Yv4yKG4YXQiRqESFu6755DBnfZQU8Znm - 2025-05-29 10:42:40 Running libp2p network backend - 2025-05-29 10:42:40 local_peer_id=12D3KooWAH8fgJv3hce7Yv4yKG4YXQiRqESFu6755DBnfZQU8Znm - 2025-05-29 10:42:40 💻 Operating system: macos - 2025-05-29 10:42:40 💻 CPU architecture: aarch64 - 2025-05-29 10:42:40 📦 Highest known block at #0 - 2025-05-29 10:42:40 Error binding to '127.0.0.1:9615': Os { code: 48, kind: AddrInUse, message: "Address already in use" } - 2025-05-29 10:42:40 Running JSON-RPC server: addr=127.0.0.1:63333,[::1]:63334 - 2025-05-29 10:42:40 🏁 CPU single core score: 1.24 GiBs, parallelism score: 1.08 GiBs with expected cores: 8 - 2025-05-29 10:42:40 🏁 Memory score: 49.42 GiBs - 2025-05-29 10:42:40 🏁 Disk score (seq. writes): 1.91 GiBs - 2025-05-29 10:42:40 🏁 Disk score (rand. writes): 529.02 MiBs - 2025-05-29 10:42:40 👶 Starting BABE Authorship worker - 2025-05-29 10:42:40 🥩 BEEFY gadget waiting for BEEFY pallet to become available... - 2025-05-29 10:42:40 Failed to trigger bootstrap: No known peers. - 2025-05-29 10:42:42 🙌 Starting consensus session on top of parent 0x1ae19030b13592b5e6fd326f26efc7b31a4f588303d348ef89ae9ebca613b8b4 (#0) - 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 - 2025-05-29 10:42:42 🔖 Pre-sealed block for proposal at 1. Hash now 0xa88d36087e7bf8ee59c1b17e0003092accf131ff8353a620410d7283657ce36a, previously 0xe046f22307fba58a3bd0cc21b1a057843d4342da8876fd44aba206f124528df0. - 2025-05-29 10:42:42 👶 New epoch 0 launching at block 0xa88d…e36a (block slot 582842054 >= start slot 582842054). - 2025-05-29 10:42:42 👶 Next epoch starts at slot 582842254 - 2025-05-29 10:42:42 🏆 Imported #1 (0x1ae1…b8b4 → 0xa88d…e36a) -
+- **`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. -For debugging purposes or to monitor low-level operations, you can enable detailed logging by setting environment variables before running the command: +**Example**: -```bash -RUST_LOG="error,evm=debug,sc_rpc_server=info,runtime::revive=debug" ./target/release/revive-dev-node --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 +}' ``` -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: +Ensure to replace the `INSERT_BLOCK_HASH` and `INSERT_TRANSACTION_INDEX` with the proper values. -```bash -./target/release/eth-rpc --dev -``` +--- -You should see logs indicating that the adapter is ready to accept connections: +### eth_getTransactionReceipt -
- ./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) -
+Returns the receipt of a transaction by transaction hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionreceipt){target=\_blank}. -Similar to the Revive Dev node, you can enable detailed logging for the ETH-RPC adapter to troubleshoot issues: +**Parameters**: -```bash -RUST_LOG="info,eth-rpc=debug" ./target/release/eth-rpc --dev -``` +- **`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. -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. +**Example**: -You can connect wallets, deploy contracts using Remix or Hardhat, and interact with your smart contracts as you would on any Ethereum-compatible network. +```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: Migration FAQs and Considerations +### eth_maxPriorityFeePerGas -- 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. +Returns an estimate of the current priority fee per gas, in Wei, to be included in a block. -# Migration FAQs and Considerations +**Parameters**: -## Introduction +None. -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. +**Example**: -## Migration Considerations +```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 +}' +``` -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. +### eth_sendRawTransaction -## Migration Checklist +Submits a raw transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendrawtransaction){target=\_blank}. -Before migrating your contracts, review this checklist: +**Parameters**: -- 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). +- **`callData` ++"string"++**: Signed transaction data. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -## Migration FAQs +**Example**: -### Which backend should I choose? +```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 +}' +``` -- Choose REVM if you want: +Ensure to replace the `INSERT_CALL_DATA` with the proper values. - - 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: +### eth_sendTransaction - - Better performance for computation-heavy applications. - - Lower execution costs for intensive operations. - - Access to next-generation smart contract features. +Creates and sends a new transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendtransaction){target=\_blank}. -If you are unsure which to choose, start with REVM for immediate compatibility, then consider PolkaVM for performance optimization once deployed. +**Parameters**: -### Do I need to rewrite my Solidity code? +- **`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. -No, for most contracts. Standard Solidity patterns work on both backends. +**Example**: -### What about factory contracts? +```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 +}' +``` -- **REVM**: Factory contracts work identically to Ethereum with no changes needed. - - The original factory pattern is: +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. - ```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. +### eth_syncing - Here's how to adapt the original factory pattern: +Returns an object with syncing data or `false` if not syncing. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_syncing){target=\_blank}. - ```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); - } - } - ``` +**Parameters**: -The deployment steps for PolkaVM factories are: +None. -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. +**Example**: -### How do gas costs compare? +```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 +}' +``` -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? +### net_listening -For REVM, any Solidity feature will function smoothly without requiring changes or adaptations. For PVM, there are considerations, as was mentioned above. +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}. -For PolkaVM, there are some considerations: +**Parameters**: -- `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). +None. -### How do I handle the existential deposit? +**Example**: -Polkadot requires accounts to maintain a minimum balance (existential deposit or ED) to remain active. +```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 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. +### net_peerCount -You typically don't need to do anything special, but be aware: +Returns the number of peers currently connected to the client. -- 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. +**Parameters**: -### Can I use my existing development tools? +None. -Yes. Both backends support: +**Example**: -- **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} -- **Testing tools**: Your existing test suites work +```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 +}' +``` -Connect to Polkadot Hub's Ethereum JSON-RPC endpoint and use your familiar workflow. +--- -## Conclusion +### net_version -Most Ethereum contracts migrate to Polkadot Hub with minimal or no changes. Use REVM for seamless compatibility or PolkaVM for enhanced performance. +Returns the current network ID as a string. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_version){target=\_blank}. -There are a few key points to keep in mind during migration: +**Parameters**: -- 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. +None. -Your existing Solidity knowledge and tooling transfer directly to Polkadot Hub, making migration straightforward for standard smart contract patterns. +**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 +}' +``` --- -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. +### system_health -# Networks +Returns information about the health of the system. -## Introduction +**Parameters**: -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. +None. -## Network Overview +**Example**: -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] +```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 +}' ``` -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. +### web3_clientVersion - In addition, parachain developers can leverage local TestNets like [Zombienet](#zombienet) and deploy upgrades on parachain TestNets. +Returns the current client version. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#web3_clientversion){target=\_blank}. -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. +**Parameters**: -!!!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. +None. -## Polkadot Development Networks +**Example**: -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. +```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 +}' +``` -## 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. +### debug_traceBlockByNumber -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. +Traces a block's execution by its number and returns a detailed execution trace for each transaction. -## Test Networks +**Parameters**: -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}. +- **`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. -### Westend +**Example**: -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. +```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 +}' +``` -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. +Ensure to replace `INSERT_BLOCK_VALUE` with a proper block number if needed. -### 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. +### debug_traceTransaction -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. +Traces the execution of a single transaction by its hash and returns a detailed execution trace. -## Local Test Networks +**Parameters**: -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. +- **`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"`). -### Zombienet +**Example**: -[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. +```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 +}' +``` -Key features of Zombienet include: +Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper value. -- 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. +### debug_traceCall -### Chopsticks +Executes a new message call and returns a detailed execution trace without creating a transaction on the blockchain. -[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. +**Parameters**: -Key features of Chopsticks include: +- **`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"`). -- 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. +**Example**: -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. +```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. --- -Page Title: Node and Runtime +## Response Format -- 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. +All responses follow the standard JSON-RPC 2.0 format: -# Node and Runtime +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": ... // The return value varies by method +} +``` -## Introduction +## Error Handling -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. +If an error occurs, the response will include an error object: -Polkadot SDK-based nodes consist of two main components, each with distinct responsibilities: the client (also called node) and the runtime. +```json +{ + "jsonrpc": "2.0", + "id": 1, + "error": { + "code": -32000, + "message": "Error message here" + } +} +``` -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 +Page Title: Local Development Node -The Polkadot SDK-based blockchain architecture is fundamentally built on two distinct yet interconnected components: +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-local-dev-node.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/dev-environments/local-dev-node/ +- Summary: Follow this step-by-step guide to install a Revive Dev node and ETH-RPC adapter for smart contract development in a local environment. -- 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. +# Local Development Node -- 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. +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. +## Introduction -### Advantages of this Architecture +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. -- **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. +By the end of this guide, you'll have: -## Node (Client) +- A running node with smart contract support. +- An ETH-RPC adapter for Ethereum-compatible tooling integration accessible at `http://localhost:8545`. -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: +## Prerequisites -- **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. +Before getting started, ensure you have done the following: -## Runtime +- 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. -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. +## Install the Revive Dev Node and ETH-RPC Adapter -### Characteristics +The 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: -The runtime is distinguished by three key characteristics: +```bash +git clone https://github.com/paritytech/polkadot-sdk.git +cd polkadot-sdk +git checkout 8e2b6f742a38bb13688e12abacded0aab2dbbb23 +``` -- **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. +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: -### Key Functions +```bash +cargo build -p revive-dev-node --bin revive-dev-node --release +cargo build -p pallet-revive-eth-rpc --bin eth-rpc --release +``` -The runtime performs several critical functions, such as: +The 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: -- Define state transition rules. -- Implement blockchain-specific logic. -- Manage account interactions. -- Control transaction processing. -- Define governance mechanisms. -- Handle custom pallets and modules. +- **Revive Dev node path**: `polkadot-sdk/target/release/revive-dev-node` +- **ETH-RPC adapter path**: `polkadot-sdk/target/release/eth-rpc` -## Communication Between Node and Runtime +## Run the Local Node -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. +With the binaries compiled, you can now start your local development environment. The setup requires running two processes. -### Runtime APIs +Start 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: -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: +```bash +./target/release/revive-dev-node --dev +``` -- Build, execute, and finalize blocks. -- Access metadata. -- Access consensus related information. -- Handle transaction execution. +The node will begin producing blocks immediately and display initialization logs: -### Host Functions +
+ ./target/release/revive-dev-node --dev +
+ 2025-05-29 10:42:35 Substrate Node + 2025-05-29 10:42:35 ✌️ version 3.0.0-dev-38b7581fc04 + 2025-05-29 10:42:35 ❤️ by Parity Technologies <admin@parity.io>, 2017-2025 + 2025-05-29 10:42:35 📋 Chain specification: Development + 2025-05-29 10:42:35 🏷 Node name: annoyed-aunt-3163 + 2025-05-29 10:42:35 👤 Role: AUTHORITY + 2025-05-29 10:42:35 💾 Database: RocksDb at /var/folders/x0/xl_kjddj3ql3bx7752yr09hc0000gn/T/substrate2P85EF/chains/dev/db/full + 2025-05-29 10:42:40 🔨 Initializing Genesis block/state (state: 0xfc05…482e, header-hash: 0x1ae1…b8b4) + 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 } + 2025-05-29 10:42:40 👴 Loading GRANDPA authority set from genesis on what appears to be first startup. + 2025-05-29 10:42:40 👶 Creating empty BABE epoch changes on what appears to be first startup. + 2025-05-29 10:42:40 Using default protocol ID "sup" because none is configured in the chain specs + 2025-05-29 10:42:40 🏷 Local node identity is: 12D3KooWAH8fgJv3hce7Yv4yKG4YXQiRqESFu6755DBnfZQU8Znm + 2025-05-29 10:42:40 Running libp2p network backend + 2025-05-29 10:42:40 local_peer_id=12D3KooWAH8fgJv3hce7Yv4yKG4YXQiRqESFu6755DBnfZQU8Znm + 2025-05-29 10:42:40 💻 Operating system: macos + 2025-05-29 10:42:40 💻 CPU architecture: aarch64 + 2025-05-29 10:42:40 📦 Highest known block at #0 + 2025-05-29 10:42:40 Error binding to '127.0.0.1:9615': Os { code: 48, kind: AddrInUse, message: "Address already in use" } + 2025-05-29 10:42:40 Running JSON-RPC server: addr=127.0.0.1:63333,[::1]:63334 + 2025-05-29 10:42:40 🏁 CPU single core score: 1.24 GiBs, parallelism score: 1.08 GiBs with expected cores: 8 + 2025-05-29 10:42:40 🏁 Memory score: 49.42 GiBs + 2025-05-29 10:42:40 🏁 Disk score (seq. writes): 1.91 GiBs + 2025-05-29 10:42:40 🏁 Disk score (rand. writes): 529.02 MiBs + 2025-05-29 10:42:40 👶 Starting BABE Authorship worker + 2025-05-29 10:42:40 🥩 BEEFY gadget waiting for BEEFY pallet to become available... + 2025-05-29 10:42:40 Failed to trigger bootstrap: No known peers. + 2025-05-29 10:42:42 🙌 Starting consensus session on top of parent 0x1ae19030b13592b5e6fd326f26efc7b31a4f588303d348ef89ae9ebca613b8b4 (#0) + 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 + 2025-05-29 10:42:42 🔖 Pre-sealed block for proposal at 1. Hash now 0xa88d36087e7bf8ee59c1b17e0003092accf131ff8353a620410d7283657ce36a, previously 0xe046f22307fba58a3bd0cc21b1a057843d4342da8876fd44aba206f124528df0. + 2025-05-29 10:42:42 👶 New epoch 0 launching at block 0xa88d…e36a (block slot 582842054 >= start slot 582842054). + 2025-05-29 10:42:42 👶 Next epoch starts at slot 582842254 + 2025-05-29 10:42:42 🏆 Imported #1 (0x1ae1…b8b4 → 0xa88d…e36a) +
-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: +For debugging purposes or to monitor low-level operations, you can enable detailed logging by setting environment variables before running the command: -- Perform cryptographic operations. -- Access the current blockchain state. -- Handle storage modifications. -- Allocate memory. +```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 +``` -Page Title: On-Chain Governance Overview +You should see logs indicating that the adapter is ready to accept connections: -- 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. +
+ ./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) +
-# On-Chain Governance +Similar to the Revive Dev node, you can enable detailed logging for the ETH-RPC adapter to troubleshoot issues: -## Introduction +```bash +RUST_LOG="info,eth-rpc=debug" ./target/release/eth-rpc --dev +``` -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. +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 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. +You can connect wallets, deploy contracts using Remix or Hardhat, and interact with your smart contracts as you would on any Ethereum-compatible network. -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: +Page Title: Migration FAQs and Considerations -- Slow voting cycles, causing delays in decision-making. -- Inflexibility in handling multiple referendums, restricting scalability. +- 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. -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. +# Migration FAQs and Considerations -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. +## Introduction -## OpenGov Key Features +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. -OpenGov transforms Polkadot’s governance into a decentralized, stakeholder-driven model, eliminating centralized decision-making bodies like the Council. Key enhancements include: +## Migration Considerations -- **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. +Take into account the following considerations before migrating your contracts: -This new system ensures Polkadot governance remains agile and inclusive, even as the ecosystem grows. +- 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. -## Origins and Tracks +## Migration Checklist -In OpenGov, origins and tracks are central to managing proposals and votes. +Before migrating your contracts, review this checklist: -- **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. +- 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). -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. +## Migration FAQs -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. +### Which backend should I choose? -## Referendums +- Choose REVM if you want: -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. + - Zero-modification deployment of existing Ethereum contracts. + - Exact EVM behavior for audited code. + - Compatibility with tools that inspect EVM bytecode. + - Rapid deployment without optimization. -The timeline for an individual referendum includes four distinct periods: +- Choose PolkaVM if you want: -- **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. + - Better performance for computation-heavy applications. + - Lower execution costs for intensive operations. + - Access to next-generation smart contract features. -### Vote on Referendums +If you are unsure which to choose, start with REVM for immediate compatibility, then consider PolkaVM for performance optimization once deployed. -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. +### Do I need to rewrite my Solidity code? -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. +No, for most contracts. Standard Solidity patterns work on both backends. -### Delegate Voting Power +### What about factory contracts? -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. +- **REVM**: Factory contracts work identically to Ethereum with no changes needed. + + The original factory pattern is: -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. + ```solidity + contract TokenFactory { + function createToken(string memory name) public returns (address) { + // Creates new contract at runtime + Token newToken = new Token(name); + return address(newToken); + } + } + ``` -Visit [Multirole Delegation](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#multirole-delegation){target=\_blank} for more details on delegating voting power. +- **PolkaVM**: Factory contracts require pre-uploading dependent contracts. -### Cancel a Referendum + Here's how to adapt the original factory pattern: -Polkadot OpenGov has two origins for rejecting ongoing referendums: + ```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); + } + } + ``` -- [**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. +The deployment steps for PolkaVM factories are: -See [Cancelling, Killing, and Blacklisting](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#cancelling-killing--blacklisting){target=\_blank} for additional information on rejecting referendums. +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. -## Additional Resources +### How do gas costs compare? -- **[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. +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. -Page Title: Overview of FRAME +For PolkaVM, there are some considerations: -- 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. +- `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). -# Customize Your Runtime +### How do I handle the existential deposit? -## Introduction +Polkadot requires accounts to maintain a minimum balance (existential deposit or ED) to remain active. -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 is handled automatically for you: -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. +- 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. -## Understanding Your Runtime +You typically don't need to do anything special, but be aware: -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. +- 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. -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. +### Can I use my existing development tools? -## Runtime Architecture +Yes. Both backends support: -The following diagram shows how FRAME components work together to form your runtime: +- **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} +- **Testing tools**: Your existing test suites work -![](/images/parachains/customize-runtime/index/frame-overview-01.webp) +Connect to Polkadot Hub's Ethereum JSON-RPC endpoint and use your familiar workflow. -The main components are: +## Conclusion -- **`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. +Most Ethereum contracts migrate to Polkadot Hub with minimal or no changes. Use REVM for seamless compatibility or PolkaVM for enhanced performance. -## Building Blocks: Pallets +There are a few key points to keep in mind during migration: -[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. +- 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. -A pallet can implement virtually any blockchain feature you need: +Your existing Solidity knowledge and tooling transfer directly to Polkadot Hub, making migration straightforward for standard smart contract patterns. -- 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. +Page Title: Networks -### Pallet Structure +- 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. -FRAME uses Rust macros extensively, allowing you to focus on your pallet's logic while the framework handles boilerplate and integration code. +# Networks -A typical pallet looks like this: +## Introduction -```rust -pub use pallet::*; +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. -#[frame_support::pallet] -pub mod pallet { - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; +## Network Overview - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(_); +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: - #[pallet::config] // snip - #[pallet::event] // snip - #[pallet::error] // snip - #[pallet::storage] // snip - #[pallet::call] // snip -} +``` mermaid +flowchart LR + id1[Local] --> id2[Westend] --> id4[Kusama] --> id5[Polkadot] + id1[Local] --> id3[Paseo] --> id5[Polkadot] ``` -Every pallet can implement these core macros: +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. -- **`#[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). +A typical journey through the Polkadot core protocol development process might look like this: -For a comprehensive reference, see the [`pallet_macros` documentation](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/index.html){target=\_blank}. +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. -## How Runtime Customization Works +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. -Customizing your runtime typically follows these patterns: +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. -**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. +4. **Polkadot**: After passing tests on Westend and Kusama, features are considered ready for deployment to Polkadot, the live production network. -**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. + In addition, parachain developers can leverage local TestNets like [Zombienet](#zombienet) and deploy upgrades on parachain TestNets. -**Combining Multiple Pallets**: Layer multiple pallets together to create complex behaviors. Pallets can call each other and share storage when needed. +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. -**Configuring Pallet Parameters**: Most pallets are configurable—you can adjust their behavior through configuration traits without modifying their code. +!!!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. -The following diagram illustrates how pallets combine to form a complete runtime: +## Polkadot Development Networks -![](/images/parachains/customize-runtime/index/frame-overview-02.webp) +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. -## Starting Templates +## Kusama Network -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. +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. -- **[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. +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. -- **[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. +## Test Networks -- **[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. +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}. -- **[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. +### Westend -## Key Customization Scenarios +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. -This section covers the most common customization patterns you'll encounter: +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. -- **[Add Existing Pallets to Your Runtime](/parachains/customize-runtime/add-existing-pallets/)**: Integrate pre-built pallets from the FRAME library with minimal configuration. +### Paseo -- **[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. +[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. -- **[Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/)**: Enable smart contract execution on your parachain using Contracts pallets. +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. -- **[Create Custom Pallets](/parachains/customize-runtime/pallet-development/create-a-pallet/)**: Build entirely custom pallets for features unique to your blockchain. +## Local Test Networks -- **[Test Your Runtime](/parachains/customize-runtime/pallet-development/pallet-testing/)**: Unit test pallets and mock complete runtimes to ensure everything works correctly. +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. -Page Title: Overview of the Polkadot Relay Chain +Key features of Zombienet include: -- 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. +- 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. -# Overview +Zombienet is ideal for developers looking to test quickly and thoroughly before moving to more resource-intensive public TestNets. -## Introduction +### Chopsticks -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}. +[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. -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. +Key features of Chopsticks include: -## Polkadot 1.0 +- 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. -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. +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. -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. +Page Title: Node and Runtime -- **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. +- 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. -- **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. +# Node and Runtime -- **Rapid L1 development**: The [Polkadot SDK](/reference/parachains/){target=\_blank} allows fast, flexible creation and deployment of Layer-1 chains. +## Introduction -- **Cultivating the next generation of Web3 developers**: Polkadot supports the growth of Web3 core developers through initiatives such as. +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 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) +Polkadot SDK-based nodes consist of two main components, each with distinct responsibilities: the client (also called node) and the runtime. -### High-Level Architecture +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. -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. +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. -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. +## Architectural Principles -Here’s a high-level overview of the Polkadot protocol architecture: +The Polkadot SDK-based blockchain architecture is fundamentally built on two distinct yet interconnected components: -![](/images/reference/polkadot-hub/consensus-and-security/relay-chain/relay-chain-01.webp){ style="background:white" } +- 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. -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. +- 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. -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. +### Advantages of this Architecture -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. +- **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. -### Polkadot's Additional Functionalities +## Node (Client) -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}. +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: -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}. +- **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. -#### Agile Coretime +## Runtime -The new and more efficient way of obtaining core on Polkadot is to go through the process of purchasing coretime. +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. -[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}. +### Characteristics -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. +The runtime is distinguished by three key characteristics: -Renewal orders are prioritized over new orders, offering stability against price fluctuations and helping parachains budget more effectively for project costs. +- **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. -### Polkadot's Resilience +### Key Functions -Decentralization is a vital component of blockchain networks, but it comes with trade-offs: +The runtime performs several critical functions, such as: -- 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. +- Define state transition rules. +- Implement blockchain-specific logic. +- Manage account interactions. +- Control transaction processing. +- Define governance mechanisms. +- Handle custom pallets and modules. -A network should be decentralized enough to prevent manipulative or malicious influence. In this sense, decentralization is a tool for achieving resilience. +## Communication Between Node and Runtime -Polkadot 1.0 currently achieves resilience through several strategies: +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. -- **Nominated Proof of Stake (NPoS)**: Ensures that the stake per validator is maximized and evenly distributed among validators. +### Runtime APIs -- **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. +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: -- **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. +- Build, execute, and finalize blocks. +- Access metadata. +- Access consensus related information. +- Handle transaction execution. -### Polkadot's Blockspace +### Host Functions -Polkadot 1.0’s design allows for the commoditization of blockspace. +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: -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. +- Perform cryptographic operations. +- Access the current blockchain state. +- Handle storage modifications. +- Allocate memory. -- **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. +Page Title: On-Chain Governance Overview -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. +- 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. -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. +# On-Chain Governance -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}. +## Introduction -## DOT Token +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. -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. +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. -### 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. +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. -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. +## Governance Evolution -### The Planck Unit +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: -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. +- Slow voting cycles, causing delays in decision-making. +- Inflexibility in handling multiple referendums, restricting scalability. -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. +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. -### Uses for DOT +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. -DOT serves three primary functions within the Polkadot network: +## OpenGov Key Features -- **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. +OpenGov transforms Polkadot’s governance into a decentralized, stakeholder-driven model, eliminating centralized decision-making bodies like the Council. Key enhancements include: -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. +- **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. -## JAM and the Road Ahead +This new system ensures Polkadot governance remains agile and inclusive, even as the ecosystem grows. -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: +## Origins and Tracks -- **Join**: Handles data integration. -- **Accumulate**: Folds computations into the chain's state. +In OpenGov, origins and tracks are central to managing proposals and votes. -JAM removes many of the opinions and constraints of the current relay chain while maintaining its core security properties. Expected improvements include: +- **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. -- **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. +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. -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. +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. -Page Title: Parachains Overview +The timeline for an individual referendum includes four distinct periods: -- 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. +- **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. -# Parachains Overview +### Vote on Referendums -## Introduction +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. -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. +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. -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. +### Delegate Voting Power -Key capabilities that parachains provide include: +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. -- **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. +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. -## Polkadot SDK: Parachain Architecture +Visit [Multirole Delegation](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#multirole-delegation){target=\_blank} for more details on delegating voting power. -Building a parachain involves understanding and utilizing several key components of the Polkadot SDK: +### Cancel a Referendum -![](/images/reference/parachains/index/overview-01.webp) +Polkadot OpenGov has two origins for rejecting ongoing referendums: -- **[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. +- [**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. -### Substrate: The Foundation +See [Cancelling, Killing, and Blacklisting](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#cancelling-killing--blacklisting){target=\_blank} for additional information on rejecting referendums. -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. +## Additional Resources -Every Polkadot SDK node consists of two main components: +- **[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. -- **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. +Page Title: Overview of FRAME - - 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. +- 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. -```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 +# Customize Your Runtime - subgraph sg1[Parachain
Node] - direction TB +## Introduction - I[RuntimeCall Executor] - B[Wasm Runtime - STF] +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. - subgraph sg2[Client] - direction TB - C[Network and Blockchain
Infrastructure Services
+ Relay Chain Interface] - end +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. - I --> B - end +## Understanding Your Runtime - class sg1 title - class sg2 clientStyle - class C clientSubNodeStyle - class I runtimeCallExecutorStyle +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. -### FRAME: Building Blocks for Your Runtime +## Runtime Architecture -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. +The following diagram shows how FRAME components work together to form your runtime: -```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 +![](/images/parachains/customize-runtime/index/frame-overview-01.webp) - 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 -``` +The main components are: -### Cumulus: Parachain-Specific Functionality +- **`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. -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. +## Building Blocks: Pallets -Key Cumulus components include: +[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. -- **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. +A pallet can implement virtually any blockchain feature you need: -## Where to Go Next +- 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. -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. +### Pre-Built Pallets vs. Custom Pallets -The following sections provide detailed guidance on each aspect of parachain development, from initial design through deployment and ongoing maintenance. +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. -- Guide __Launch a Simple Parachain__ +### Pallet Structure - --- +FRAME uses Rust macros extensively, allowing you to focus on your pallet's logic while the framework handles boilerplate and integration code. - Walk through the complete parachain launch flow: from setup and deployment to obtaining coretime. +A typical pallet looks like this: - [:octicons-arrow-right-24: Deploy](/parachains/launch-a-parachain/set-up-the-parachain-template/) +```rust +pub use pallet::*; +#[frame_support::pallet] +pub mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; -- Guide __Customize Your Runtime__ + #[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 +} +``` - Design your parachain's runtime logic and choose appropriate pallets for your use case. +Every pallet can implement these core macros: - [:octicons-arrow-right-24: Get Started](/parachains/customize-runtime/) +- **`#[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). -- Guide __Interoperability__ +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 - Implement XCM for trustless cross-chain communication with other parachains. +Customizing your runtime typically follows these patterns: - [:octicons-arrow-right-24: Learn More](/parachains/interoperability/get-started/) +**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. -- Guide __Runtime Upgrades__ +**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. - Upgrade your parachain's runtime without hard forks using forkless upgrade mechanisms. +**Configuring Pallet Parameters**: Most pallets are configurable—you can adjust their behavior through configuration traits without modifying their code. - [:octicons-arrow-right-24: Maintain](/parachains/runtime-maintenance/runtime-upgrades/) +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. -Page Title: Polkadot SDK Accounts +- **[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. -- 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. +- **[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. -# Accounts +- **[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. -## Introduction +- **[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. -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. +## Key Customization Scenarios -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. +This section covers the most common customization patterns you'll encounter: -## Account Data Structure +- **[Add Existing Pallets to Your Runtime](/parachains/customize-runtime/add-existing-pallets/)**: Integrate pre-built pallets from the FRAME library with minimal configuration. -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. +- **[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. -### Account +- **[Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/)**: Enable smart contract execution on your parachain using Contracts pallets. -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. +- **[Create Custom Pallets](/parachains/customize-runtime/pallet-development/create-a-pallet/)**: Build entirely custom pallets for features unique to your blockchain. -The code snippet below shows how accounts are defined: +- **[Test Your Runtime](/parachains/customize-runtime/pallet-development/pallet-testing/)**: Unit test pallets and mock complete runtimes to ensure everything works correctly. -```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: +Page Title: Overview of the Polkadot Relay Chain -- **`_`**: 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: +- 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. - - **`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`. +# Overview -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. +## Introduction -### Account Info +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}. -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. +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. -```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, -} -``` +## Polkadot 1.0 -The `AccountInfo` structure includes the following components: +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. -- **`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. +As a Layer-0 blockchain, Polkadot contributes to the multi-chain vision through several key innovations and initiatives, including: -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. +- **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. -### Account Reference Counters +- **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. -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. +- **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. -The reference counters include: +- **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. -- **`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. +- **Rapid L1 development**: The [Polkadot SDK](/reference/parachains/){target=\_blank} allows fast, flexible creation and deployment of Layer-1 chains. -#### Providers Reference Counters +- **Cultivating the next generation of Web3 developers**: Polkadot supports the growth of Web3 core developers through initiatives such as. -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. + - [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) -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. +### High-Level Architecture -#### Consumers Reference Counters +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. -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. +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. -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. +Here’s a high-level overview of the Polkadot protocol architecture: -#### Sufficients Reference Counter +![](/images/reference/polkadot-hub/consensus-and-security/relay-chain/relay-chain-01.webp){ style="background:white" } -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. +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. -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. +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. -#### Account Deactivation +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. -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 Additional Functionalities -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. +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}. -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. +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}. -#### Updating Counters +#### Agile Coretime -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 new and more efficient way of obtaining core on Polkadot is to go through the process of purchasing coretime. -The following helper functions manage these counters: +[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}. -- **`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. +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. -To ensure proper account cleanup and lifecycle management, a corresponding decrement should be made for each increment action. +Renewal orders are prioritized over new orders, offering stability against price fluctuations and helping parachains budget more effectively for project costs. -The `System` pallet offers three query functions to assist developers in tracking account states: +### Polkadot's Resilience -- **[`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. +Decentralization is a vital component of blockchain networks, but it comes with trade-offs: -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. - +- 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. -## Account Balance Types +A network should be decentralized enough to prevent manipulative or malicious influence. In this sense, decentralization is a tool for achieving resilience. -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. +Polkadot 1.0 currently achieves resilience through several strategies: -!!! 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): +- **Nominated Proof of Stake (NPoS)**: Ensures that the stake per validator is maximized and evenly distributed among validators. - ```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: +- **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. - ```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. +- **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. -### Balance Types +### Polkadot's Blockspace -The five main balance types are: +Polkadot 1.0’s design allows for the commoditization of blockspace. -- **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. +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. -The spendable balance is calculated as follows: +- **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). -```text -spendable = free - max(locked - reserved, ED) -``` +- **Flexibility**: Reflects the functionalities and types of data that can be stored, with high-quality data essential to avoid bottlenecks in critical processes. -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. +- **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. -### Locks +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. -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. +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. -Locks follow these basic rules: +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}. -- 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. +## DOT Token -#### Locks Example +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. -Consider an example where an account has 80 DOT locked for both staking and governance purposes like so: +### 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. -- 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. +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. -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. +### The Planck Unit -![Illustration of Lock Example](/images/reference/parachains/accounts/accounts-01.webp) +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. -#### Edge Cases for Locks +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. -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}. +### Uses for DOT -### Balance Types on Polkadot.js +DOT serves three primary functions within the Polkadot network: -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. +- **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. -![](/images/reference/parachains/accounts/accounts-02.webp) +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 most common balance types displayed on Polkadot.js are: +## JAM and the Road Ahead -- **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. +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: -- **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. +- **Join**: Handles data integration. +- **Accumulate**: Folds computations into the chain's state. -- **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. +JAM removes many of the opinions and constraints of the current relay chain while maintaining its core security properties. Expected improvements include: -- **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. +- **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. -- **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. +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. -- **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. +Page Title: Parachains Overview -By understanding these balance types and their implications, developers and users can better manage their funds and engage with on-chain activities more effectively. +- 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. -## Address Formats +# Parachains Overview -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. +## Introduction -### Basic Format +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. -SS58 addresses consist of three main components: +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. -```text -base58encode(concat(,
, )) -``` +Key capabilities that parachains provide include: -- **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. +- **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. -### Address Type +## Polkadot SDK: Parachain Architecture -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: +Building a parachain involves understanding and utilizing several key components of the Polkadot SDK: -- **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. +![](/images/reference/parachains/index/overview-01.webp) -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. +- **[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. -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. +### Substrate: The Foundation -### Address Length +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. -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. +Every Polkadot SDK node consists of two main components: -| 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 | +- **Client (Host)**: Handles infrastructure services. -SS58 addresses also support different payload sizes, allowing a flexible range of account identifiers. + - 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. -### Checksum Types +- **Runtime (State Transition Function)**: Contains your business logic. -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. + - 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. -The checksum ensures that an address is not modified or corrupted, adding an extra layer of security for account management. +```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 -### Validating Addresses + subgraph sg1[Parachain
Node] + direction TB -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. + I[RuntimeCall Executor] + B[Wasm Runtime - STF] -#### Using Subkey + subgraph sg2[Client] + direction TB + C[Network and Blockchain
Infrastructure Services
+ Relay Chain Interface] + end -[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. + I --> B + end -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: + class sg1 title + class sg2 clientStyle + class C clientSubNodeStyle + class I runtimeCallExecutorStyle -```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. +### FRAME: Building Blocks for Your Runtime -For example, to inspect the public keys derived from a secret seed phrase, you can run a command similar to the following: +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. -```bash -subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very" +```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 ``` -The command displays output similar to the following: +### Cumulus: Parachain-Specific Functionality -
- 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 -
+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. -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. +Key Cumulus components include: -However, not all addresses in Polkadot SDK-based networks are based on keys. +- **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. -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: +## Where to Go Next -```bash -subkey inspect "12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU" -``` +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 command displays output similar to the following: +The following sections provide detailed guidance on each aspect of parachain development, from initial design through deployment and ongoing maintenance. -
- 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 +- Guide __Launch a Simple Parachain__ -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'); + Walk through the complete parachain launch flow: from setup and deployment to obtaining coretime. -// Specify an address to test. -const address = 'INSERT_ADDRESS_TO_TEST'; + [:octicons-arrow-right-24: Deploy](/parachains/launch-a-parachain/set-up-the-parachain-template/) -// Check address -const isValidSubstrateAddress = () => { - try { - encodeAddress(isHex(address) ? hexToU8a(address) : decodeAddress(address)); - return true; - } catch (error) { - return false; - } -}; +- Guide __Customize Your Runtime__ -// Query result -const isValid = isValidSubstrateAddress(); -console.log(isValid); + --- -``` + Design your parachain's runtime logic and choose appropriate pallets for your use case. -If the function returns `true`, the specified address is a valid address. + [:octicons-arrow-right-24: Get Started](/parachains/customize-runtime/) -#### Other SS58 Implementations +- Guide __Interoperability__ -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} + 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: 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. + Upgrade your parachain's runtime without hard forks using forkless upgrade mechanisms. -# Randomness + [:octicons-arrow-right-24: Maintain](/parachains/runtime-maintenance/runtime-upgrades/) -## 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. +Page Title: Polkadot SDK Accounts -## VRF +- 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. -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. +# Accounts -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). +## Introduction -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. +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. -### How VRF Works +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. -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. +## Account Data Structure -In each slot, validators execute a "die roll" using a VRF. The VRF uses three inputs: +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. -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. +### Account -This process helps maintain fair randomness across the network. +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. -Here is a graphical representation: +The code snippet below shows how accounts are defined: -![](/images/reference/parachains/randomness/randomness-01.webp) +```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 VRF produces two outputs: a result (the random number) and a proof (verifying that the number was generated correctly). +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 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 `StorageMap` consists of the following parameters: -The validator then attempts to create a block, submitting it along with the `PROOF` and `RESULT`. +- **`_`**: 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: -So, VRF can be expressed like: + - **`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`. -`(RESULT, PROOF) = VRF(SECRET, EPOCH_RANDOMNESS_VALUE, CURRENT_SLOT_NUMBER)` +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. -Put simply, performing a "VRF roll" generates a random number along with proof that the number was genuinely produced and not arbitrarily chosen. +### Account Info -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. +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. -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. +```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, +} +``` -Because validators roll independently, no block candidates may appear in some slots if all roll numbers are above the threshold. +The `AccountInfo` structure includes the following components: -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. +- **`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. -## RANDAO +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. -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. +### Account Reference Counters -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. +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. -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. +The reference counters include: -## VDFs +- **`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. -Verifiable Delay Functions (VDFs) are time-bound computations that, even on parallel computers, take a set amount of time to complete. +#### Providers Reference Counters -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. +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. -However, VDF likely requires specialized ASIC devices to run separately from standard nodes. +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. -!!!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. +#### Consumers Reference Counters -## Additional Resources +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. -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. +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. -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. +#### 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. -Page Title: Register a Local Asset +#### Account Deactivation -- 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. +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. -# Register a Local Asset on Asset Hub +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. -## Introduction +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. -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. +#### Updating Counters -This guide will take you through the steps of registering a local asset on the Asset Hub parachain. +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. -## Prerequisites +The following helper functions manage these counters: -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. +- **`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. -- 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. +To ensure proper account cleanup and lifecycle management, a corresponding decrement should be made for each increment action. -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. +The `System` pallet offers three query functions to assist developers in tracking account states: -## Steps to Register a Local Asset +- **[`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. -To register a local asset on the Asset Hub parachain, follow these steps: +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. + -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. +## Account Balance Types - - 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. +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. -2. Click on the **Network** tab on the top navigation bar and select **Assets** from the dropdown list. +!!! 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): - ![Access to Asset Hub through Polkadot.JS](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-01.webp) + ```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: -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. + ```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. - ![Asset IDs on Asset Hub](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-02.webp) +### Balance Types -4. Once you have confirmed that the asset ID is unique, click on the **Create** button on the top right corner of the page. +The five main balance types are: - ![Create a new asset](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-03.webp) +- **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. -5. Fill in the required fields in the **Create Asset** form: +The spendable balance is calculated as follows: - 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) +```text +spendable = free - max(locked - reserved, ED) +``` -6. Choose the accounts for the roles listed below: +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. - 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. +### Locks - ![Admin, Issuer, Freezer accounts](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-05.webp) +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. -7. Click on the **Sign and Submit** button to complete the asset registration process. +Locks follow these basic rules: - ![Sign and Submit](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-06.webp) +- 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. -## Verify Asset Registration +#### Locks 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. +Consider an example where an account has 80 DOT locked for both staking and governance purposes like so: -![Asset listed on Polkadot.js Apps](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-07.webp) +- 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. -!!! 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 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. -In this way, you have successfully registered a local asset on the Asset Hub parachain. +![Illustration of Lock Example](/images/reference/parachains/accounts/accounts-01.webp) -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. +#### Edge Cases for Locks -## Test Setup Environment +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}. -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. +### Balance Types on Polkadot.js -To set up a test environment, execute the following command: +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. -```bash -npx @acala-network/chopsticks \ ---config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot-asset-hub.yml -``` +![](/images/reference/parachains/accounts/accounts-02.webp) -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. +The most common balance types displayed on Polkadot.js are: -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. +- **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. -Page Title: Set Up the Polkadot SDK Parachain Template +- **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. -- 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. +- **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. -# Set Up the Polkadot SDK Parachain Template +- **Bonded balance**: The tokens locked for staking purposes. Bonded tokens are not transferable until they are unbonded after the unbonding period. -## Introduction +- **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. -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. +- **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. -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. +By understanding these balance types and their implications, developers and users can better manage their funds and engage with on-chain activities more effectively. -This guide walks you through the full process of working with this template. You will: +## Address Formats -- 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 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. -By the end of this guide, you'll have a working template ready to customize and deploy as a parachain. +### Basic Format -## Prerequisites +SS58 addresses consist of three main components: -Before getting started, ensure you have done the following: +```text +base58encode(concat(,
, )) +``` -- 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. +- **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. -For this tutorial series, you need to use Rust `1.86`. Newer versions of the compiler may not work with this parachain template version. +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. -Run the following commands to set up the correct Rust version: +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. -=== "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 - ``` +### Address Type -=== "Ubuntu" +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: - ```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 - ``` +- **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. -## Polkadot SDK Utility Tools +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. -This tutorial requires two essential tools: +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. -- [**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 - ``` +### Address Length - This command installs the `chain-spec-builder` binary. +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. -- [**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. +| 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 | - To install it, run the following command: +SS58 addresses also support different payload sizes, allowing a flexible range of account identifiers. - ```bash - cargo install --locked polkadot-omni-node@0.5.0 - ``` +### Checksum Types - This command installs the `polkadot-omni-node` binary. +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. -## Clone the Template +The checksum ensures that an address is not modified or corrupted, adding an extra layer of security for account management. -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: +### Validating Addresses -1. Clone the template repository: +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. - ```bash - git clone https://github.com/paritytech/polkadot-sdk-parachain-template.git parachain-template - ``` +#### Using Subkey -2. Navigate into the project directory: +[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. - ```bash - cd parachain-template - ``` +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: -## Explore the Project Structure +```bash +subkey inspect [flags] [options] uri +``` -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. +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. -The template follows a standard Polkadot SDK project layout: +For example, to inspect the public keys derived from a secret seed phrase, you can run a command similar to the following: -```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 +```bash +subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very" ``` -Key directories explained: +The command displays output similar to the following: -- **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. +
+ 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 +
-!!!note - The runtime is compiled to WebAssembly (Wasm), enabling forkless upgrades. The node binary remains constant while the runtime can be updated on-chain. +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. -## Compile the Runtime +However, not all addresses in Polkadot SDK-based networks are based on keys. -Now that you understand the template structure, let's compile the runtime to ensure everything is working correctly. +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: -1. Compile the runtime: +```bash +subkey inspect "12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU" +``` - ```bash - cargo build --release --locked - ``` +The command displays output similar to the following: - !!!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. +
+ 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 +
-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` +#### Using Polkadot.js API -## Verify the Build +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: -After compilation completes, verify that the runtime was created successfully by checking for the Wasm blob: +```js +// Import Polkadot.js API dependencies +const { decodeAddress, encodeAddress } = require('@polkadot/keyring'); +const { hexToU8a, isHex } = require('@polkadot/util'); -```bash -ls -la ./target/release/wbuild/parachain-template-runtime/ -``` +// Specify an address to test. +const address = 'INSERT_ADDRESS_TO_TEST'; -You should see the `parachain_template_runtime.compact.compressed.wasm` file in the output, confirming the build was successful. +// Check address +const isValidSubstrateAddress = () => { + try { + encodeAddress(isHex(address) ? hexToU8a(address) : decodeAddress(address)); -## Run the Node Locally + return true; + } catch (error) { + return false; + } +}; -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. +// Query result +const isValid = isValidSubstrateAddress(); +console.log(isValid); -Follow these steps to launch your node in development mode: +``` -1. Generate the chain specification file of your parachain: +If the function returns `true`, the specified address is a valid address. - ```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 - ``` +#### Other SS58 Implementations -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: +Support for encoding and decoding Polkadot SDK SS58 addresses has been implemented in several other languages and libraries. - ```bash - polkadot-omni-node --chain ./chain_spec.json --dev - ``` +- **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} - 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. +Page Title: Randomness -4. Confirm that your blockchain is producing new blocks by checking if the number after `finalized` is increasing in the output. +- 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. -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. +# Randomness -## Interact with the Node +## Introduction -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: +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. -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) +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. -2. Connect to your local node: +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. - 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) +## VRF -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) +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. -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'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). -## Stop the Node +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. -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. +### How VRF Works -To stop the local node: +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. -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. +In each slot, validators execute a "die roll" using a VRF. The VRF uses three inputs: -## Where to Go Next +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. -- Tutorial __Deploy to Polkadot__ +Here is a graphical representation: - --- +![](/images/reference/parachains/randomness/randomness-01.webp) - Learn how to deploy your parachain template to a relay chain testnet. Configure your chain specification, register as a parachain, and start producing blocks. +The VRF produces two outputs: a result (the random number) and a proof (verifying that the number was generated correctly). - [:octicons-arrow-right-24: Get Started](/parachains/launch-a-parachain/deploy-to-polkadot.md) +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)` -Page Title: Smart Contracts Cookbook Index +Put simply, performing a "VRF roll" generates a random number along with proof that the number was genuinely produced and not arbitrarily chosen. -- 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 +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. -Welcome to the Polkadot smart contracts cookbook index. +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. -This page contains a list of all relevant tutorials and guides to help you get started coding smart contracts and dApps in Polkadot. +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. -## Get Tokens from the Faucet +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. -| 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. | +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. -## EVM/PVM Smart Contracts +## VDFs -| 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. | +Verifiable Delay Functions (VDFs) are time-bound computations that, even on parallel computers, take a set amount of time to complete. -## Port Ethereum DApps +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. -| 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. | +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 -Page Title: Smart Contracts Overview +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. -- 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. +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. -# 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. +Page Title: Register a Local Asset -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. +- 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. -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. +# Register a Local Asset on Asset Hub -## Native Smart Contracts +## Introduction -### 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. -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. +This guide will take you through the steps of registering a local asset on the Asset Hub parachain. -### Smart Contract Development +## Prerequisites -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. +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. -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. +- 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. -### Technical Architecture +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. -PolkaVM, the underlying virtual machine, utilizes a RISC-V-based register architecture _optimized for the Polkadot ecosystem_. This design choice offers several advantages: +## Steps to Register a Local Asset -- Enhanced performance for smart contract execution. -- Improved gas efficiency for complex operations. -- Native compatibility with Polkadot's runtime environment. -- Optimized storage and state management. +To register a local asset on the Asset Hub parachain, follow these steps: -### Development Tools and Resources +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. -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: + - 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. -- 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. +2. Click on the **Network** tab on the top navigation bar and select **Assets** from the dropdown list. -### Cross-Chain Capabilities + ![Access to Asset Hub through Polkadot.JS](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-01.webp) -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. +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. -### Use Cases + ![Asset IDs on Asset Hub](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-02.webp) -Polkadot Hub's smart contract platform is suitable for a wide range of applications: +4. Once you have confirmed that the asset ID is unique, click on the **Create** button on the top right corner of the page. -- 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. + ![Create a new asset](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-03.webp) -## Other Smart Contract Environments +5. Fill in the required fields in the **Create Asset** form: -Beyond Polkadot Hub's native PolkaVM support, the ecosystem offers two main alternatives for smart contract development: + 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) -- **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). +6. Choose the accounts for the roles listed below: -- **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. + 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) -Each environment provides unique advantages based on developer preferences and application requirements. +7. Click on the **Sign and Submit** button to complete the asset registration process. -## Where to Go Next + ![Sign and Submit](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-06.webp) -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. +## Verify Asset Registration -Subsequent sections of this guide provide detailed information about specific development tools, advanced features, and best practices for building on Polkadot Hub. +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) -- Guide __Libraries__ +!!! 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. - Explore essential libraries to optimize smart contract development and interaction. +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. - [:octicons-arrow-right-24: Reference](/smart-contracts/libraries/ethers-js/) +## Test Setup Environment -- Guide __Dev Environments__ +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: - Set up your development environment for seamless contract deployment and testing. +```bash +npx @acala-network/chopsticks \ +--config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot-asset-hub.yml +``` - [:octicons-arrow-right-24: Reference](/smart-contracts/dev-environments/local-dev-node/) +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: Technical Reference Overview +Page Title: Set Up the Polkadot SDK Parachain Template -- 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. +- 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 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. +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. -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. +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 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. +This guide walks you through the full process of working with this template. You will: -## Polkadot Hub +- 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. -[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. +By the end of this guide, you'll have a working template ready to customize and deploy as 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: +## Prerequisites -- **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. +Before getting started, ensure you have done the following: -## Parachains +- 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. -[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: +For this tutorial series, you need to use Rust `1.86`. Newer versions of the compiler may not work with this parachain template version. -- **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}. +Run the following commands to set up the correct Rust version: -## On-Chain Governance +=== "macOS" -[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: + ```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 + ``` -- **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. +=== "Ubuntu" -## Glossary + ```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 + ``` -The [Glossary](/reference/glossary/){target=\_blank} provides quick-reference definitions for Polkadot-specific terminology. Essential terms include: +## Polkadot SDK Utility Tools -- 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) +This tutorial requires two essential tools: -## 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 + ``` -The [Tools](/reference/tools/){target=\_blank} section documents essential development and interaction tools for the Polkadot ecosystem: + This command installs the `chain-spec-builder` binary. -- **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. +- [**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. -## Where to Go Next + To install it, run the following command: -For detailed exploration of specific areas, proceed to any of the main sections: + ```bash + cargo install --locked polkadot-omni-node@0.5.0 + ``` -
+ This command installs the `polkadot-omni-node` binary. -- Learn **Polkadot Hub** +## 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: - Understand the relay chain's role in coordinating parachains, providing shared security, and enabling governance. +1. Clone the template repository: - [:octicons-arrow-right-24: Reference](/reference/polkadot-hub/) + ```bash + git clone https://github.com/paritytech/polkadot-sdk-parachain-template.git parachain-template + ``` -- Learn **Parachains** +2. Navigate into the project directory: - --- + ```bash + cd parachain-template + ``` - Deep dive into parachain architecture, consensus, data structures, and building application-specific blockchains. +## Explore the Project Structure - [:octicons-arrow-right-24: Reference](/reference/parachains/) +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. -- Learn **On-Chain Governance** +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 +``` - Explore Polkadot's decentralized governance framework and how to participate in network decision-making. +Key directories explained: - [:octicons-arrow-right-24: Reference](/reference/governance/) +- **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. -- Guide **Glossary** +!!!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 - Quick reference for Polkadot-specific terminology and concepts used throughout the documentation. +Now that you understand the template structure, let's compile the runtime to ensure everything is working correctly. - [:octicons-arrow-right-24: Reference](/reference/glossary/) +1. Compile the runtime: -- Guide **Tools** + ```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. - Discover development tools, libraries, and frameworks for building and interacting with Polkadot. +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` - [:octicons-arrow-right-24: Reference](/reference/tools/) +## 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. -Page Title: Transactions +## Run the Node Locally -- 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. +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. -# Transactions +Follow these steps to launch your node in development mode: -## Introduction +1. Generate the chain specification file of your parachain: -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. + ```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 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. +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: -## What Is a Transaction? + ```bash + polkadot-omni-node --chain ./chain_spec.json --dev + ``` -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. + The `--dev` option does the following: -There are three primary types of transactions (extrinsics) in the Polkadot SDK: + - Deletes all active data (keys, blockchain database, networking information) when stopped. + - Ensures a clean working state each time you restart the node. -- **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. +3. Verify that your node is running by reviewing the terminal output. You should see log messages indicating block production and finalization. -Each type serves a distinct purpose, and understanding when and how to use each is key to efficiently working with the Polkadot SDK. +4. Confirm that your blockchain is producing new blocks by checking if the number after `finalized` is increasing in the output. -### Signed Transactions +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 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. +## Interact with the Node -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. +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: -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. +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) -### Unsigned Transactions +2. Connect to your local node: -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. + 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) -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. +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) -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. +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. -### Inherent Transactions +## Stop the Node -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. +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. -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. +To stop the local node: -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. +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. -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. +## Where to Go Next -## 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. +- Tutorial __Deploy to Polkadot__ -### Types of Transaction Formats + --- -In Polkadot SDK-based chains, extrinsics can fall into three main categories: + Learn how to deploy your parachain template to a relay chain testnet. Configure your chain specification, register as a parachain, and start producing blocks. -- **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. + [:octicons-arrow-right-24: Get Started](/parachains/launch-a-parachain/deploy-to-polkadot.md) -### 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: +Page Title: Smart Contracts Cookbook Index -``` code - + + -``` +- 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. -Each part of the signed transaction has a purpose, ensuring the transaction's authenticity and context within the blockchain. +# Smart Contracts Cookbook -### Signed Extensions +Welcome to the Polkadot smart contracts cookbook index. -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. +This page contains a list of all relevant tutorials and guides to help you get started coding smart contracts and dApps in Polkadot. -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: +## Get Tokens from the Faucet -- **[`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. +| 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. | -These extensions are critical in the transaction lifecycle, ensuring that only valid and prioritized transactions are processed. +## EVM/PVM Smart Contracts -## Transaction Construction +| 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. | -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. +## Port Ethereum DApps -### Construct a Signed Transaction +| 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. | -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. +Page Title: Smart Contracts Overview -2. **Create a signing payload**: Once the unsigned payload is ready, additional data must be included: +- 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 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. +# 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. +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. +## Introduction -The following is an example of how a signed transaction might look: +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. -``` 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 -) -``` +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 Encoding +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. -Before a transaction is sent to the network, it is serialized and encoded using a structured encoding process that ensures consistency and prevents tampering: +## Native Smart Contracts -- **`[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. +### Introduction -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. +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. -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. +### Smart Contract Development -### Customize Transaction Construction +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. -Although the basic steps for constructing transactions are consistent across Polkadot SDK-based chains, developers can customize transaction formats and validation rules. For example: +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. -- **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. +### Technical Architecture -By leveraging Polkadot SDK's modular design, developers can create highly specialized transaction logic tailored to their chain's needs. +PolkaVM, the underlying virtual machine, utilizes a RISC-V-based register architecture _optimized for the Polkadot ecosystem_. This design choice offers several advantages: -## Lifecycle of a Transaction +- Enhanced performance for smart contract execution. +- Improved gas efficiency for complex operations. +- Native compatibility with Polkadot's runtime environment. +- Optimized storage and state management. -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. +### Development Tools and Resources -### Define Transaction Properties +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 Polkadot SDK runtime defines key transaction properties, such as: +- 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 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. +### Cross-Chain Capabilities -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. +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. -### Process on a Block Authoring Node +### Use Cases -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. +Polkadot Hub's smart contract platform is suitable for a wide range of applications: -![Transaction lifecycle diagram](/images/reference/parachains/blocks-transactions-fees/transactions/transactions-01.webp){ style="background:white" } +- 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. -### Validate and Queue +## Other Smart Contract Environments -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: +Beyond Polkadot Hub's native PolkaVM support, the ecosystem offers two main alternatives for smart contract development: -- **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. +- **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). -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. +- **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. -#### 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. +Each environment provides unique advantages based on developer preferences and application requirements. -The transaction pool organizes transactions into two queues: +## Where to Go Next -- **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. +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. -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. +Subsequent sections of this guide provide detailed information about specific development tools, advanced features, and best practices for building on Polkadot Hub. -#### 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: +- Guide __Libraries__ -- 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 + Explore essential libraries to optimize smart contract development and interaction. -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: + [:octicons-arrow-right-24: Reference](/smart-contracts/libraries/ethers-js/) -- **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. +- Guide __Dev Environments__ -### 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. + Set up your development environment for seamless contract deployment and testing. -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. + [:octicons-arrow-right-24: Reference](/smart-contracts/dev-environments/local-dev-node/) -## 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. +Page Title: Technical Reference Overview -- **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. +- 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. -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. +## Introduction -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. +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. -## Unique Identifiers for Extrinsics +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. -Transaction hashes are **not unique identifiers** in Polkadot SDK-based chains. +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. -Key differences from traditional blockchains: +## Polkadot Hub -- Transaction hashes serve only as fingerprints of transaction information. -- Multiple valid transactions can share the same hash. -- Hash uniqueness assumptions lead to serious issues. +[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. -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: +The Hub encompasses a set of core functionality that enables developers and users to build and interact with applications on Polkadot. Key capabilities include: -| 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 | +- **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. -Notice that blocks 100 and 200 contain transactions with identical hashes (0x01) but are completely different, valid operations occurring at different times. +## Parachains -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. +[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: -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. +- **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}. -## Additional Resources +## On-Chain Governance -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. +[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: Transactions and Fees on Asset Hub +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/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. +- 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) -# Blocks, Transactions, and Fees +## Tools -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction +The [Tools](/reference/tools/){target=\_blank} section documents essential development and interaction tools for the Polkadot ecosystem: -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. +- **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. -## Smart Contract Blocks +## Where to Go Next -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. +For detailed exploration of specific areas, proceed to any of the main sections: -## 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. +- Learn **Polkadot Hub** -### EVM Transaction Types + --- -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: + Understand the relay chain's role in coordinating parachains, providing shared security, and enabling governance. -- **[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. + [:octicons-arrow-right-24: Reference](/reference/polkadot-hub/) -- **[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. +- Learn **Parachains** -- **[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. + --- -- **[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. + Deep dive into parachain architecture, consensus, data structures, and building application-specific blockchains. -Each transaction type can exist in both signed and unsigned states, with appropriate validation and processing mechanisms for each. + [:octicons-arrow-right-24: Reference](/reference/parachains/) -## Fees and Gas +- Learn **On-Chain Governance** -Asset Hub implements a sophisticated resource management system that combines parachain transaction fees with EVM gas mechanics, providing both Ethereum compatibility and enhanced features. + --- -### Gas Model Overview + Explore Polkadot's decentralized governance framework and how to participate in network decision-making. -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. + [:octicons-arrow-right-24: Reference](/reference/governance/) -- **Dynamic gas scaling**: Asset Hub implements a dynamic pricing mechanism that reflects actual execution performance. This results in: +- Guide **Glossary** - - 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. + --- -- **Multi-dimensional resource metering**: Asset Hub extends beyond the traditional single-metric gas model to track three distinct resources. + Quick reference for Polkadot-specific terminology and concepts used throughout the documentation. - - `ref_time` (computation time): + [:octicons-arrow-right-24: Reference](/reference/glossary/) - - Functions as traditional gas equivalent. - - Measures actual computational resource usage. - - Primary metric for basic operation costs. +- Guide **Tools** + --- - - `proof_size` (verification overhead): + Discover development tools, libraries, and frameworks for building and interacting with Polkadot. - - Tracks state proof size required for validator verification. - - Helps manage consensus-related resource consumption. - - Important for cross-chain operations. + [:octicons-arrow-right-24: Reference](/reference/tools/) +
- - `storage_deposit` (state management): - - Manages blockchain state growth. - - Implements a deposit-based system for long-term storage. - - Refundable when storage is freed. +--- -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. +Page Title: Transactions -### Fee Components +- 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. -- Base fees: +# Transactions - - Storage deposit for contract deployment. - - Minimum transaction fee for network access. - - Network maintenance costs. +## Introduction -- Execution fees: +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. - - Computed based on gas consumption. - - Converted to native currency using network-defined rates. - - Reflects actual computational resource usage. +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. -- Storage fees: +## What Is a Transaction? - - Deposit for long-term storage usage. - - Refundable when storage is freed. - - Helps prevent state bloat. +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. -### Gas Calculation and Conversion +There are three primary types of transactions (extrinsics) in the Polkadot SDK: -The system maintains precise conversion mechanisms between: +- **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. -- Substrate weights and EVM gas units. -- Native currency and gas costs. -- Different resource metrics within the multi-dimensional model. +Each type serves a distinct purpose, and understanding when and how to use each is key to efficiently working with the Polkadot SDK. -This ensures accurate fee calculation while maintaining compatibility with existing Ethereum tools and workflows. +### 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. -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 +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. -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: +### Unsigned Transactions -- Memory usage -- Storage input and output -- Computation -- Transaction and block size -- State database size +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 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. +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. -[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. +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. -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. +### Inherent Transactions -[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. +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. -## How Fees are Calculated +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. -The final fee for a transaction is calculated using the following parameters: +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. -- **`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. +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 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. +## Transaction Formats -```text -inclusion fee = base fee + weight fee + length fee -``` +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. -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. +### Types of Transaction Formats -## Using the Transaction Payment Pallet +In Polkadot SDK-based chains, extrinsics can fall into three main categories: -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: +- **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. -- 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}. +### Signed Transaction Data Structure -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}. +A signed transaction typically includes the following components: -### Understanding the Inclusion Fee +- **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. -The formula for calculating the inclusion fee is as follows: +Here's a simplified breakdown of how signed transactions are typically constructed in a Polkadot SDK runtime: -```text -inclusion_fee = base_fee + length_fee + [targeted_fee_adjustment * weight_fee] +``` code + + + ``` -And then, for calculating the final fee: +Each part of the signed transaction has a purpose, ensuring the transaction's authenticity and context within the blockchain. -```text -final_fee = inclusion_fee + tip -``` +### Signed Extensions -In the first formula, the `targeted_fee_adjustment` is a multiplier that can tune the final fee based on the network’s congestion. +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 `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. +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. -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}. +In FRAME, a signed extension can hold any of the following types by default: -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. +- **[`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. -### Accounts with an Insufficient Balance +Signed extensions can enforce checks like: -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. +- **[`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. -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. +These extensions are critical in the transaction lifecycle, ensuring that only valid and prioritized transactions are processed. -### Fee Multipliers +## Transaction Construction -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. +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. -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}. +### Construct a Signed Transaction -## Transactions with Special Requirements +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: -Inclusion fees must be computable before execution and can only represent fixed logic. Some transactions warrant limiting resources with other strategies. For example: +1. **Construct the unsigned payload**: Gather the necessary information for the call, including: -- 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. + - **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. -It is important to note that if you query the chain for a transaction fee, it only returns the inclusion fee. +2. **Create a signing payload**: Once the unsigned payload is ready, additional data must be included: -## Default Weight Annotations + - **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. -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: +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. -```rust -#[pallet::weight(100_000)] -fn my_dispatchable() { - // ... -} +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 +) ``` -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. +### Transaction Encoding -### Weights and Database Read/Write Operations +Before a transaction is sent to the network, it is serialized and encoded using a structured encoding process that ensures consistency and prevents tampering: -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: +- **`[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. -```rust -#[pallet::weight(T::DbWeight::get().reads_writes(1, 2) + 20_000)] -fn my_dispatchable() { - // ... -} -``` +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. -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: +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. -- 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. +### Customize Transaction Construction -### Dispatch Classes +Although the basic steps for constructing transactions are consistent across Polkadot SDK-based chains, developers can customize transaction formats and validation rules. For example: -Dispatches are broken into three classes: +- **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. -- Normal -- Operational -- Mandatory +By leveraging Polkadot SDK's modular design, developers can create highly specialized transaction logic tailored to their chain's needs. -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: +## Lifecycle of a Transaction -```rust -#[pallet::dispatch((DispatchClass::Operational))] -fn my_dispatchable() { - // ... -} -``` +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. -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: +### Define Transaction Properties -```rust -#[pallet::dispatch(DispatchClass::Normal, Pays::No)] -fn my_dispatchable() { - // ... -} -``` +The Polkadot SDK runtime defines key transaction properties, such as: -#### Normal Dispatches +- **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. -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. +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. -#### Operational Dispatches +### Process on a Block Authoring Node -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}. +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. -#### Mandatory Dispatches +![Transaction lifecycle diagram](/images/reference/parachains/blocks-transactions-fees/transactions/transactions-01.webp){ style="background:white" } -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: +### Validate and Queue -- The operation performed is always light. -- The operation can only be included in a block once. +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: -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. +- **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. -### Dynamic Weights +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. -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: +#### Transaction Pool -```rust -use frame_support:: { - dispatch:: { - DispatchClass::Normal, - Pays::Yes, - }, - weights::Weight, -}; +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. -#[pallet::weight(FunctionOf( - |args: (&Vec,)| args.0.len().saturating_mul(10_000), - ) -] -fn handle_users(origin, calls: Vec) { - // Do something per user -} -``` +The transaction pool organizes transactions into two queues: -## Post Dispatch Weight Correction +- **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. -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: +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. -```rust -#[pallet::weight(10_000 + 500_000_000)] -fn expensive_or_cheap(input: u64) -> DispatchResultWithPostInfo { - let was_heavy = do_calculation(input); +#### Invalid Transactions - 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()) - } -} -``` +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: -## Custom Fees +- 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. -You can also define custom fee systems through custom weight functions or inclusion fee functions. +### Transaction Ordering and Priority -### Custom Weights +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: -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: +- **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. -- [`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. +### Transaction Execution -`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. +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. -```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 - } -} +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. -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 - } - } -} +## Transaction Mortality -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 - } - } -} -``` +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. -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: +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 -struct CustomWeight; -impl WeighData<(&u32, &u64)> for CustomWeight { - fn weigh_data(&self, target: (&u32, &u64)) -> Weight { - ... - } -} +- **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. -// given a dispatch: -#[pallet::call] -impl, I: 'static> Pallet { - #[pallet::weight(CustomWeight)] - fn foo(a: u32, b: u64) { ... } -} -``` +- **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. -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 ``. +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. -#### Custom Inclusion Fee +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. -The following example illustrates how to customize your inclusion fee. You must configure the appropriate associated types in the respective module. +## Unique Identifiers for Extrinsics -```rust -// Assume this is the balance type -type Balance = u64; +Transaction hashes are **not unique identifiers** in Polkadot SDK-based chains. -// 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 - } -} +Key differences from traditional blockchains: -parameter_types! { - pub const ExtrinsicBaseWeight: Weight = 10_000_000; -} +- Transaction hashes serve only as fingerprints of transaction information. +- Multiple valid transactions can share the same hash. +- Hash uniqueness assumptions lead to serious issues. -impl frame_system::Config for Runtime { - type ExtrinsicBaseWeight = ExtrinsicBaseWeight; -} +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: -parameter_types! { - pub const TransactionByteFee: Balance = 10; -} +| 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 | -impl transaction_payment::Config { - type TransactionByteFee = TransactionByteFee; - type WeightToFee = CustomWeightToFee; - type FeeMultiplierUpdate = TargetedFeeAdjustment; -} +Notice that blocks 100 and 200 contain transactions with identical hashes (0x01) but are completely different, valid operations occurring at different times. -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 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. -## Additional Resources +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. -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. +## Additional Resources -- [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 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: Use Hardhat with Polkadot Hub +Page Title: Transactions and Fees on Asset 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. +- 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. -# Hardhat +# 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**. -
-- :octicons-code-16:{ .lg .middle } __Test and Deploy with Hardhat__ +## Introduction - --- +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. - Master Solidity smart contract development with Hardhat. Learn testing, deployment, and network interaction in one comprehensive tutorial. +## Smart Contract Blocks -
- [:octicons-arrow-right-24: Get Started](/tutorials/smart-contracts/launch-your-first-project/test-and-deploy-with-hardhat){target=\_blank} +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 -!!! 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. +Asset Hub implements a sophisticated transaction system that supports various transaction types and formats, encompassing both traditional parachain operations and EVM-specific interactions. - 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. +### EVM Transaction Types -## Overview +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: -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. +- **[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. -## Prerequisites +- **[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. -Before getting started, ensure you have: +- **[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. -- [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. +- **[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. -## Set Up Hardhat +Each transaction type can exist in both signed and unsigned states, with appropriate validation and processing mechanisms for each. -1. Create a new directory for your project and navigate into it: +## Fees and Gas - ```bash - mkdir hardhat-example - cd hardhat-example - ``` +Asset Hub implements a sophisticated resource management system that combines parachain transaction fees with EVM gas mechanics, providing both Ethereum compatibility and enhanced features. -2. Initialize a new npm project: +### Gas Model Overview - ```bash - npm init -y - ``` +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. -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: +- **Dynamic gas scaling**: Asset Hub implements a dynamic pricing mechanism that reflects actual execution performance. This results in: - ```bash - npm install --save-dev @parity/hardhat-polkadot@0.1.9 - ``` + - 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. -4. Create a Hardhat project: +- **Multi-dimensional resource metering**: Asset Hub extends beyond the traditional single-metric gas model to track three distinct resources. - ```bash - npx hardhat-polkadot init - ``` + - `ref_time` (computation time): - Select **Create a JavaScript project** when prompted and follow the instructions. After that, your project will be created with three main folders: + - Functions as traditional gas equivalent. + - Measures actual computational resource usage. + - Primary metric for basic operation costs. - - **`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: + - `proof_size` (verification overhead): - ```bash - echo '/ignition/deployments/' >> .gitignore - ``` + - Tracks state proof size required for validator verification. + - Helps manage consensus-related resource consumption. + - Important for cross-chain operations. -6. Finish the setup by installing all the dependencies: - ```bash - npm install - ``` + - `storage_deposit` (state management): - !!! 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. + - Manages blockchain state growth. + - Implements a deposit-based system for long-term storage. + - Refundable when storage is freed. -## Compile Your Contract +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. -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: +### Fee Components -- **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. +- Base fees: -To compile your project, follow these instructions: + - Storage deposit for contract deployment. + - Minimum transaction fee for network access. + - Network maintenance costs. -1. Modify your Hardhat configuration file to specify which compilation process you will be using and activate the `polkavm` flag in the Hardhat network: +- Execution fees: - === "npm Configuration" + - Computed based on gas consumption. + - Converted to native currency using network-defined rates. + - Reflects actual computational resource usage. - ```javascript title="hardhat.config.js" hl_lines="9-11 14" - // hardhat.config.js - require('@nomicfoundation/hardhat-toolbox'); +- Storage fees: - require('@parity/hardhat-polkadot'); + - Deposit for long-term storage usage. + - Refundable when storage is freed. + - Helps prevent state bloat. - /** @type import('hardhat/config').HardhatUserConfig */ - module.exports = { - solidity: '0.8.28', - resolc: { - compilerSource: 'npm', - }, - networks: { - hardhat: { - polkavm: true, - }, - }, - }; - ``` +### Gas Calculation and Conversion - === "Binary Configuration" +The system maintains precise conversion mechanisms between: - ```javascript title="hardhat.config.js" hl_lines="9-14 17" - // hardhat.config.js - require('@nomicfoundation/hardhat-toolbox'); +- Substrate weights and EVM gas units. +- Native currency and gas costs. +- Different resource metrics within the multi-dimensional model. - require('@parity/hardhat-polkadot'); +This ensures accurate fee calculation while maintaining compatibility with existing Ethereum tools and workflows. - /** @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: +Page Title: Transactions Weights and Fees - ```javascript title="hardhat.config.js" hl_lines="4-10" - resolc: { - ... - settings: { - optimizer: { - enabled: true, - parameters: 'z', - fallbackOz: true, - runs: 200, - }, - standardJson: true, - }, - ... - } - ``` +- 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. - 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. +# Transactions Weights and Fees -2. Compile the contract with Hardhat: +## Introductions - ```bash - npx hardhat compile - ``` +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: -3. After successful compilation, you'll see the artifacts generated in the `artifacts-pvm` directory: +- Memory usage +- Storage input and output +- Computation +- Transaction and block size +- State database size - ```bash - ls artifacts-pvm/contracts/*.sol/ - ``` +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. - You should see JSON files containing the contract ABI and bytecode of the contracts you compiled. +[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. -## Set Up a Testing Environment +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. -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. +[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. -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. +## How Fees are Calculated -Configure a local node setup by adding the node binary path along with the ETH-RPC adapter path: +The final fee for a transaction is calculated using the following parameters: -```javascript title="hardhat.config.js" hl_lines="12-20" -// hardhat.config.js -require('@nomicfoundation/hardhat-toolbox'); +- **`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. -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, - }, - }, - }, -}; +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 ``` -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. +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. -!!! 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. +## Using the Transaction Payment Pallet -Once configured, start your chosen testing environment with: +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: -```bash -npx hardhat node -``` +- 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}. -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`. +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}. -The output will be something like this: +### Understanding the Inclusion Fee -
- 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 - ... -
+The formula for calculating the inclusion fee is as follows: -## Test Your Contract +```text +inclusion_fee = base_fee + length_fee + [targeted_fee_adjustment * weight_fee] +``` -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. +And then, for calculating the final fee: -To run your test: +```text +final_fee = inclusion_fee + tip +``` -1. Update the `hardhat.config.js` file accordingly to the [Set Up a Testing Environment](#set-up-a-testing-environment) section. +In the first formula, the `targeted_fee_adjustment` is a multiplier that can tune the final fee based on the network’s congestion. -2. Execute the following command to run your tests: +- 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. - ```bash - npx hardhat test - ``` +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}. -## Deploy to a Local Node +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. -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: +### Accounts with an Insufficient Balance -1. Update the Hardhat configuration file to add the local network as a target for local deployment: +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. - ```javascript title="hardhat.config.js" hl_lines="13-16" - // hardhat.config.js - require('@nomicfoundation/hardhat-toolbox'); +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. - require('@parity/hardhat-polkadot'); - /** @type import('hardhat/config').HardhatUserConfig */ - module.exports = { - ... - networks: { - hardhat: { - ... - }, - localNode: { - polkavm: true, - url: `http://127.0.0.1:8545`, - }, - }, - }, - }; - ``` +### Fee Multipliers -2. Start a local node: +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. - ```bash - npx hardhat node - ``` +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}. - This command will spawn a local Substrate node along with the ETH-RPC adapter. +## Transactions with Special Requirements -3. In a new terminal window, deploy the contract using Ignition: +Inclusion fees must be computable before execution and can only represent fixed logic. Some transactions warrant limiting resources with other strategies. For example: - ```bash - npx hardhat ignition deploy ./ignition/modules/MyToken.js --network localNode - ``` +- 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. -## Deploying to a Live Network +It is important to note that if you query the chain for a transaction fee, it only returns the inclusion fee. -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: +## Default Weight Annotations -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. +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: -2. Export your private key and save it in your Hardhat environment: +```rust +#[pallet::weight(100_000)] +fn my_dispatchable() { + // ... +} +``` - ```bash - npx hardhat vars set PRIVATE_KEY "INSERT_PRIVATE_KEY" - ``` +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. - 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}. +### Weights and Database Read/Write Operations - !!! 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. +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: -3. Check that your private key has been set up successfully by running: +```rust +#[pallet::weight(T::DbWeight::get().reads_writes(1, 2) + 20_000)] +fn my_dispatchable() { + // ... +} +``` - ```bash - npx hardhat vars get PRIVATE_KEY - ``` +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: -4. Update your Hardhat configuration file with network settings for the Polkadot network you want to target: +- 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. - ```javascript title="hardhat.config.js" hl_lines="18-22" - // hardhat.config.js - require('@nomicfoundation/hardhat-toolbox'); +### Dispatch Classes - require('@parity/hardhat-polkadot'); - const { vars } = require('hardhat/config'); +Dispatches are broken into three classes: - /** @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')], - }, - }, - }, - }; - ``` +- Normal +- Operational +- Mandatory -6. Deploy your contract using Ignition: +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: - ```bash - npx hardhat ignition deploy ./ignition/modules/MyToken.js --network polkadotHubTestnet - ``` +```rust +#[pallet::dispatch((DispatchClass::Operational))] +fn my_dispatchable() { + // ... +} +``` -## Interacting with Your Contract +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: -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. +```rust +#[pallet::dispatch(DispatchClass::Normal, Pays::No)] +fn my_dispatchable() { + // ... +} +``` -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`). +#### Normal Dispatches -```javascript title="interact.js" -const hre = require('hardhat'); +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. -async function main() { - // Get the contract factory - const MyToken = await hre.ethers.getContractFactory('MyToken'); +#### Operational Dispatches - // Replace with your deployed contract address - const contractAddress = 'INSERT_CONTRACT_ADDRESS'; +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}. - // Attach to existing contract - const token = await MyToken.attach(contractAddress); +#### Mandatory Dispatches - // Get signers - const [deployer] = await hre.ethers.getSigners(); +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: - // 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); +- The operation performed is always light. +- The operation can only be included in a block once. - 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`, - ); -} +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. -main().catch((error) => { - console.error(error); - process.exitCode = 1; -}); +### 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: -Run your interaction script: +```rust +use frame_support:: { + dispatch:: { + DispatchClass::Normal, + Pays::Yes, + }, + weights::Weight, +}; -```bash -npx hardhat run scripts/interact.js --network polkadotHubTestnet +#[pallet::weight(FunctionOf( + |args: (&Vec,)| args.0.len().saturating_mul(10_000), + ) +] +fn handle_users(origin, calls: Vec) { + // Do something per user +} ``` -## Upgrading the Plugin +## Post Dispatch Weight Correction -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: +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: -```bash -rm -rf node_modules package-lock.json +```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()) + } +} ``` -After that, you can upgrade the plugin to the latest version by running the following commands: +## Custom Fees -```bash -npm install --save-dev @parity/hardhat-polkadot@latest -npm install -``` +You can also define custom fee systems through custom weight functions or inclusion fee functions. -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. +### Custom Weights -## Where to Go Next +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: -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. +- [`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. -Explore more about smart contracts through these resources: +`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 + } +} -- Guide __Get Started with Smart Contracts__ +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 + } + } +} +``` - Learn how to get started with smart contracts +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: - [:octicons-arrow-right-24: Get Started](/smart-contracts/get-started/) +```rust +struct CustomWeight; +impl WeighData<(&u32, &u64)> for CustomWeight { + fn weigh_data(&self, target: (&u32, &u64)) -> Weight { + ... + } +} -- External __Hardhat Documentation__ +// 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 ``. - Learn more about Hardhat's advanced features and best practices. +#### Custom Inclusion Fee - [:octicons-arrow-right-24: Get Started](https://hardhat.org/docs){target=\_blank} +The following example illustrates how to customize your inclusion fee. You must configure the appropriate associated types in the respective module. -- External __OpenZeppelin Contracts__ +```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 + } +} - Test your skills by deploying contracts with prebuilt templates. +parameter_types! { + pub const ExtrinsicBaseWeight: Weight = 10_000_000; +} - [:octicons-arrow-right-24: Get Started](https://www.openzeppelin.com/solidity-contracts){target=\_blank} +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 + } +} +``` -Page Title: Use the Polkadot Remix IDE +## Additional Resources -- 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. +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. -# Remix IDE +- [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} -!!! 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. +Page Title: Use Hardhat with Polkadot Hub -
- [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/){target=\_blank} +- 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. -- :octicons-code-16:{ .lg .middle } __Deploy ERC20s Using Remix IDE__ +# 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__ --- - Mint your custom ERC-20 token on Polkadot's Asset Hub. Leverage PolkaVM and Polkadot Remix IDE to bring your blockchain project to life. + Master Solidity smart contract development with Hardhat. Learn testing, deployment, and network interaction in one comprehensive tutorial.
- [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/){target=\_blank} + [:octicons-arrow-right-24: Get Started](/tutorials/smart-contracts/launch-your-first-project/test-and-deploy-with-hardhat){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. +!!! 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 -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. +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: -- A web browser with [Talisman](https://talisman.xyz/){target=\_blank} extension installed. +- [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 WND test tokens to cover transaction fees (easily obtainable from the [Polkadot faucet](https://faucet.polkadot.io/westend?parachain=1000){target=\_blank}). - -## Accessing 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. - -![](/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. +- 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. -## Creating a New Contract +## Set Up Hardhat -To create a new contract using the Polkadot Remix IDE, you can follow these steps: +1. Create a new directory for your project and navigate into it: -1. Select the **Create a new file** button in the `contracts` folder. + ```bash + mkdir hardhat-example + cd hardhat-example + ``` - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-2.webp) +2. Initialize a new npm project: -2. Name your file with a `.sol` extension, in this case, `Counter.sol`. + ```bash + npm init -y + ``` - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-3.webp) +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: -3. Write your Solidity code in the editor. + ```bash + npm install --save-dev @parity/hardhat-polkadot@0.1.9 + ``` - You can use the following code as an example: +4. Create a Hardhat project: - ???- "Counter.sol" - - ```solidity - // SPDX-License-Identifier: MIT - pragma solidity ^0.8.0; + ```bash + npx hardhat-polkadot init + ``` - contract Counter { - int256 private count; + Select **Create a JavaScript project** when prompted and follow the instructions. After that, your project will be created with three main folders: - function increment() public { - count += 1; - } + - **`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. - function decrement() public { - count -= 1; - } +5. Add the following folder to the `.gitignore` file if it is not already there: - function getCount() public view returns (int256) { - return count; - } - } - ``` + ```bash + echo '/ignition/deployments/' >> .gitignore + ``` - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-4.webp) +6. Finish the setup by installing all the dependencies: + ```bash + npm install + ``` -## Compiling Your Contract + !!! 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. -1. To compile your contract, you need to: +## Compile Your Contract - 1. Navigate to the **Solidity Compiler** tab (third icon in the left sidebar). - 2. Select **Compile** or use `Ctrl+S`. +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: - ![](/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. +- **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. -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. - 2. The `Counter_metadata.json` and the `Counter.json` files have been generated. +To compile your project, follow these instructions: - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-6.webp) +1. Modify your Hardhat configuration file to specify which compilation process you will be using and activate the `polkavm` flag in the Hardhat network: -## Deploying Contracts + === "npm Configuration" -1. To deploy your contract, you need to: + ```javascript title="hardhat.config.js" hl_lines="9-11 14" + // hardhat.config.js + require('@nomicfoundation/hardhat-toolbox'); - 1. Navigate to the **Deploy & Run Transactions** tab (fourth icon in the left sidebar). - 2. Click the **Environment** dropdown. - 3. Select **Customize this list**. + require('@parity/hardhat-polkadot'); - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-7.webp) + /** @type import('hardhat/config').HardhatUserConfig */ + module.exports = { + solidity: '0.8.28', + resolc: { + compilerSource: 'npm', + }, + networks: { + hardhat: { + polkavm: true, + }, + }, + }; + ``` -2. Enable the **Injected Provider - Talisman** option. + === "Binary Configuration" - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-8.webp) + ```javascript title="hardhat.config.js" hl_lines="9-14 17" + // hardhat.config.js + require('@nomicfoundation/hardhat-toolbox'); -4. Click again the **Environment** dropdown and select **Injected Provider - Talisman**. + require('@parity/hardhat-polkadot'); - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-9.webp) + /** @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, + }, + }, + }; + ``` -4. Click the **Deploy** button and then click **Approve** in the Talisman wallet popup. + 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. - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-10.webp) + 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: -5. Once your contract is deployed successfully, you will see the following output in the Remix terminal: + ```javascript title="hardhat.config.js" hl_lines="4-10" + resolc: { + ... + settings: { + optimizer: { + enabled: true, + parameters: 'z', + fallbackOz: true, + runs: 200, + }, + standardJson: true, + }, + ... + } + ``` - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-11.webp) + 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. -## Interacting with Contracts +2. Compile the contract with Hardhat: -Once deployed, your contract appears in the **Deployed/Unpinned Contracts** section: + ```bash + npx hardhat compile + ``` -1. Expand the contract to view available methods. +3. After successful compilation, you'll see the artifacts generated in the `artifacts-pvm` directory: - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-12.webp) + ```bash + ls artifacts-pvm/contracts/*.sol/ + ``` - !!! tip - Pin your frequently used contracts to the **Pinned Contracts** section for easy access. + You should see JSON files containing the contract ABI and bytecode of the contracts you compiled. -2. To interact with the contract, you can select any of the exposed methods. +## Set Up a Testing Environment - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-13.webp) +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. - 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: +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. - - **Red**: Modifies state and is payable. - - **Orange**: Modifies state only. - - **Blue**: Reads state. +Configure a local node setup by adding the node binary path along with the ETH-RPC adapter path: -## Where to Go Next +```javascript title="hardhat.config.js" hl_lines="12-20" +// hardhat.config.js +require('@nomicfoundation/hardhat-toolbox'); -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. +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, + }, + }, + }, +}; +``` -Explore more about smart contracts through these resources: +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. -- Guide __Smart Contracts on Polkadot__ +Once configured, start your chosen testing environment with: - --- +```bash +npx hardhat node +``` - Dive into advanced smart contract concepts. +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`. - [:octicons-arrow-right-24: Get Started](/smart-contracts/) +The output will be something like this: -- External __OpenZeppelin Contracts__ - - --- +
+ 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 skills by deploying a simple contracts with prebuilt templates. +## Test Your Contract - [:octicons-arrow-right-24: Get Started](https://www.openzeppelin.com/solidity-contracts){target=\_blank} +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: -Page Title: viem for Polkadot Hub Smart Contracts + ```bash + npx hardhat test + ``` -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-viem.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/libraries/viem/ -- Summary: This guide covers deploying and interacting with contracts on Polkadot Hub using viem, a TypeScript library for Ethereum-compatible chains. +## Deploy to a Local Node -# viem +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: -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction +1. Update the Hardhat configuration file to add the local network as a target for local deployment: -[viem](https://viem.sh/){target=\_blank} is a lightweight TypeScript library designed for interacting with Ethereum-compatible blockchains. This comprehensive guide will walk you through using viem to interact with and deploy smart contracts to Polkadot Hub. + ```javascript title="hardhat.config.js" hl_lines="13-16" + // hardhat.config.js + require('@nomicfoundation/hardhat-toolbox'); -## Prerequisites + require('@parity/hardhat-polkadot'); + /** @type import('hardhat/config').HardhatUserConfig */ + module.exports = { + ... + networks: { + hardhat: { + ... + }, + localNode: { + polkavm: true, + url: `http://127.0.0.1:8545`, + }, + }, + }, + }; + ``` -Before getting started, ensure you have the following installed: +2. Start a local node: -- **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. + ```bash + npx hardhat node + ``` -## Project Structure + This command will spawn a local Substrate node along with the ETH-RPC adapter. -This project organizes contracts, scripts, and compiled artifacts for easy development and deployment. +3. In a new terminal window, deploy the contract using Ignition: -```text -viem-project/ -├── package.json -├── tsconfig.json -├── src/ -│ ├── chainConfig.ts -│ ├── createClient.ts -│ ├── createWallet.ts -│ ├── compile.ts -│ ├── deploy.ts -│ └── interact.ts -├── contracts/ -│ └── Storage.sol -└── artifacts/ - ├── Storage.json - └── Storage.polkavm -``` + ```bash + npx hardhat ignition deploy ./ignition/modules/MyToken.js --network localNode + ``` -## Set Up the Project +## Deploying to a Live Network -First, create a new folder and initialize your project: +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: -```bash -mkdir viem-project -cd viem-project -npm init -y -``` +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. -## Install Dependencies +2. Export your private key and save it in your Hardhat environment: -Install viem along with other necessary dependencies, including [@parity/resolc](https://www.npmjs.com/package/@parity/resolc){target=\_blank}, which enables to compile smart contracts to [PolkaVM](/smart-contracts/for-eth-devs/#polkavm){target=\_blank} bytecode: + ```bash + npx hardhat vars set PRIVATE_KEY "INSERT_PRIVATE_KEY" + ``` -```bash -# Install viem and resolc -npm install viem @parity/resolc + 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}. -# Install TypeScript and development dependencies -npm install --save-dev typescript ts-node @types/node -``` + !!! 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. -## Initialize Project +3. Check that your private key has been set up successfully by running: -Initialize a TypeScript project by running the following command: + ```bash + npx hardhat vars get PRIVATE_KEY + ``` -```bash -npx tsc --init -``` +4. Update your Hardhat configuration file with network settings for the Polkadot network you want to target: -Add the following scripts to your `package.json` file to enable running TypeScript files: + ```javascript title="hardhat.config.js" hl_lines="18-22" + // hardhat.config.js + require('@nomicfoundation/hardhat-toolbox'); -```json -{ - "scripts": { - "client": "ts-node src/createClient.ts", - "compile": "ts-node src/compile.ts", - "deploy": "ts-node src/deploy.ts", - "interact": "ts-node src/interact.ts" - }, -} -``` + require('@parity/hardhat-polkadot'); + const { vars } = require('hardhat/config'); -Create a directory for your TypeScript source files: + /** @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')], + }, + }, + }, + }; + ``` -```bash -mkdir src -``` +6. Deploy your contract using Ignition: -## Set Up the Chain Configuration + ```bash + npx hardhat ignition deploy ./ignition/modules/MyToken.js --network polkadotHubTestnet + ``` -The first step is to set up the chain configuration. Create a new file at `src/chainConfig.ts`: +## Interacting with Your Contract -```typescript title="src/chainConfig.ts" -import { http } from 'viem'; +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. -export const TRANSPORT = http('INSERT_RPC_URL'); +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`). -// Configure the Polkadot Hub chain -export const POLKADOT_HUB = { - id: INSERT_CHAIN_ID, - name: 'INSERT_CHAIN_NAME', - network: 'INSERT_NETWORK_NAME', - nativeCurrency: { - decimals: INSERT_CHAIN_DECIMALS, - name: 'INSERT_CURRENCY_NAME', - symbol: 'INSERT_CURRENCY_SYMBOL', - }, - rpcUrls: { - default: { - http: ['INSERT_RPC_URL'], - }, - }, -} as const; -``` +```javascript title="interact.js" +const hre = require('hardhat'); -Ensure to replace `INSERT_RPC_URL`, `INSERT_CHAIN_ID`, `INSERT_CHAIN_NAME`, `INSERT_NETWORK_NAME`, `INSERT_CHAIN_DECIMALS`, `INSERT_CURRENCY_NAME`, and `INSERT_CURRENCY_SYMBOL` with the proper values. Check the [Connect to Polkadot](/smart-contracts/connect/){target=\_blank} page for more information on the possible values. +async function main() { + // Get the contract factory + const MyToken = await hre.ethers.getContractFactory('MyToken'); -## Set Up the viem Client + // Replace with your deployed contract address + const contractAddress = 'INSERT_CONTRACT_ADDRESS'; -To interact with the chain, you need to create a client that is used solely for reading data. To accomplish this, create a new file at `src/createClient.ts`: + // Attach to existing contract + const token = await MyToken.attach(contractAddress); -```typescript title="src/createClient.ts" -import { createPublicClient, createWalletClient, http } from 'viem'; + // Get signers + const [deployer] = await hre.ethers.getSigners(); -const transport = http('INSERT_RPC_URL'); + // 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); -// Configure the Polkadot Hub chain -const assetHub = { - id: INSERT_CHAIN_ID, - name: 'INSERT_CHAIN_NAME', - network: 'INSERT_NETWORK_NAME', - nativeCurrency: { - decimals: INSERT_CHAIN_DECIMALS, - name: 'INSERT_CURRENCY_NAME', - symbol: 'INSERT_CURRENCY_SYMBOL', - }, - rpcUrls: { - default: { - http: ['INSERT_RPC_URL'], - }, - }, -} as const; + 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`, + ); +} -// Create a public client for reading data -export const publicClient = createPublicClient({ - chain: assetHub, - transport, +main().catch((error) => { + console.error(error); + process.exitCode = 1; }); ``` -After setting up the [Public Client](https://viem.sh/docs/clients/public#public-client){target=\_blank}, you can begin querying the blockchain. Here's an example of fetching the latest block number: +Run your interaction script: -??? code "Fetch Last Block code" +```bash +npx hardhat run scripts/interact.js --network polkadotHubTestnet +``` - ```js title="src/fetchLastBlock.ts" - import { createPublicClient, http } from 'viem'; +## Upgrading the Plugin - const transport = http('https://testnet-passet-hub-eth-rpc.polkadot.io'); +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: - // Configure the Polkadot Hub chain - const polkadotHubTestnet = { - id: 420420422, - name: 'Polkadot Hub TestNet', - network: 'polkadot-hub-testnet', - nativeCurrency: { - decimals: 18, - name: 'PAS', - symbol: 'PAS', - }, - rpcUrls: { - default: { - http: ['https://testnet-passet-hub-eth-rpc.polkadot.io'], - }, - }, - } as const; +```bash +rm -rf node_modules package-lock.json +``` - // Create a public client for reading data - export const publicClient = createPublicClient({ - chain: polkadotHubTestnet, - transport, - }); +After that, you can upgrade the plugin to the latest version by running the following commands: - const main = async () => { - try { - const block = await publicClient.getBlock(); - console.log('Last block: ' + block.number.toString()); - } catch (error: unknown) { - console.error('Error connecting to Polkadot Hub TestNet: ' + error); - } - }; +```bash +npm install --save-dev @parity/hardhat-polkadot@latest +npm install +``` - main(); - ``` +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. -## Set Up a Wallet +## Where to Go Next -In case you need to sign transactions, you will need to instantiate a [Wallet Client](https://viem.sh/docs/clients/wallet#wallet-client){target=\_blank} object within your project. To do so, create `src/createWallet.ts`: +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. -```typescript title="src/createWallet.ts" -import { privateKeyToAccount } from 'viem/accounts'; -import { createWalletClient, http } from 'viem'; +Explore more about smart contracts through these resources: -const transport = http('INSERT_RPC_URL'); +
-// Configure the Polkadot Hub chain -const assetHub = { - id: INSERT_CHAIN_ID, - name: 'INSERT_CHAIN_NAME', - network: 'INSERT_NETWORK_NAME', - nativeCurrency: { - decimals: INSERT_CHAIN_DECIMALS, - name: 'INSERT_CURRENCY_NAME', - symbol: 'INSERT_CURRENCY_SYMBOL', - }, - rpcUrls: { - default: { - http: ['INSERT_RPC_URL'], - }, - public: { - http: ['INSERT_RPC_URL'], - }, - }, -} as const; +- Guide __Get Started with Smart Contracts__ -// Create a wallet client for writing data -export const createWallet = (privateKey: `0x${string}`) => { - const account = privateKeyToAccount(privateKey); - return createWalletClient({ - account, - chain: assetHub, - transport, - }); -}; -``` + --- -!!!note - The wallet you import with your private key must have sufficient funds to pay for transaction fees when deploying contracts or interacting with them. Make sure to fund your wallet with the appropriate native tokens for the network you're connecting to. + Learn how to get started with smart contracts -## Sample Smart Contract + [:octicons-arrow-right-24: Get Started](/smart-contracts/get-started/) -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. +- External __Hardhat Documentation__ -```bash -mkdir contracts artifacts -``` + --- -You can use the following contract to interact with the blockchain. Paste the following contract in `contracts/Storage.sol`: + Learn more about Hardhat's advanced features and best practices. -```solidity title="contracts/Storage.sol" -//SPDX-License-Identifier: MIT + [:octicons-arrow-right-24: Get Started](https://hardhat.org/docs){target=\_blank} -// 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; +- External __OpenZeppelin Contracts__ -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; - } -} -``` + Test your skills by deploying contracts with prebuilt templates. -## Compile the Contract + [:octicons-arrow-right-24: Get Started](https://www.openzeppelin.com/solidity-contracts){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. -Create a new file at `src/compile.ts` for handling contract compilation: +--- -```typescript title="src/compile.ts" -import { compile } from '@parity/resolc'; -import { readFileSync, writeFileSync } from 'fs'; -import { basename, join } from 'path'; +Page Title: Use the Polkadot Remix IDE -const compileContract = async ( - solidityFilePath: string, - outputDir: string -): Promise => { - try { - // Read the Solidity file - const source: string = readFileSync(solidityFilePath, 'utf8'); +- 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. - // Construct the input object for the compiler - const input: Record = { - [basename(solidityFilePath)]: { content: source }, - }; +# Remix IDE - console.log(`Compiling contract: ${basename(solidityFilePath)}...`); +!!! 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__ - // 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}`); + Mint your NFT on Polkadot's Asset Hub. Use PolkaVM and OpenZeppelin to bring your digital asset to life with Polkadot Remix IDE. - // Write the ABI - const abiPath = join(outputDir, `${name}.json`); - writeFileSync(abiPath, JSON.stringify(contract.abi, null, 2)); - console.log(`ABI saved to ${abiPath}`); +
+ [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/){target=\_blank} - // Write the bytecode - if ( - contract.evm && - contract.evm.bytecode && - contract.evm.bytecode.object - ) { - const bytecodePath = join(outputDir, `${name}.polkavm`); - writeFileSync( - bytecodePath, - Buffer.from(contract.evm.bytecode.object, 'hex') - ); - console.log(`Bytecode saved to ${bytecodePath}`); - } else { - console.warn(`No bytecode found for contract: ${name}`); - } - } - } - } catch (error) { - console.error('Error compiling contracts:', error); - } -}; +- :octicons-code-16:{ .lg .middle } __Deploy ERC20s Using Remix IDE__ -const solidityFilePath: string = './contracts/Storage.sol'; -const outputDir: string = './artifacts/'; + --- -compileContract(solidityFilePath, outputDir); -``` + Mint your custom ERC-20 token on Polkadot's Asset Hub. Leverage PolkaVM and Polkadot Remix IDE to bring your blockchain project to life. -To compile your contract: +
+ [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/){target=\_blank} +
-```bash -npm run compile -``` +!!! warning + The Polkadot Remix IDE's contract compilation functionality is currently limited to Google Chrome. Alternative browsers are not recommended for this task. -After executing this script, you will see the compilation results including the generated `Storage.json` (containing the contract's ABI) and `Storage.polkavm` (containing the compiled bytecode) files in the `artifacts` folder. These files contain all the necessary information for deploying and interacting with your smart contract on Polkadot Hub. +## Overview -## Deploy the Contract +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. -Create a new file at `src/deploy.ts` for handling contract deployment: +## Prerequisites -```typescript title="src/deploy.ts" -import { readFileSync } from 'fs'; -import { join } from 'path'; -import { createWallet } from './createWallet'; -import { publicClient } from './createClient'; +Before getting started, ensure you have: -const deployContract = async ( - contractName: string, - privateKey: `0x${string}` -) => { - try { - console.log(`Deploying ${contractName}...`); +- A web browser with [Talisman](https://talisman.xyz/){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}). - // Read contract artifacts - const abi = JSON.parse( - readFileSync( - join(__dirname, '../artifacts', `${contractName}.json`), - 'utf8' - ) - ); - const bytecode = `0x${readFileSync( - join(__dirname, '../artifacts', `${contractName}.polkavm`) - ).toString('hex')}` as `0x${string}`; +## Accessing Remix IDE - // Create wallet - const wallet = createWallet(privateKey); +Navigate to [https://remix.polkadot.io/](https://remix.polkadot.io/){target=\_blank}. The interface will load with a default workspace containing sample contracts. - // Deploy contract - const hash = await wallet.deployContract({ - abi, - bytecode, - args: [], // Add constructor arguments if needed - }); +![](/images/smart-contracts/dev-environments/remix/get-started/remix-1.webp) - // Wait for deployment - const receipt = await publicClient.waitForTransactionReceipt({ hash }); - const contractAddress = receipt.contractAddress; +In this interface, you can access a file explorer, edit your code, interact with various plugins for development, and use a terminal. - console.log(`Contract deployed at: ${contractAddress}`); - return contractAddress; - } catch (error) { - console.error('Deployment failed:', error); - throw error; - } -}; +## Creating a New Contract -const privateKey = 'INSERT_PRIVATE_KEY'; -deployContract('Storage', privateKey); -``` +To create a new contract using the Polkadot Remix IDE, you can follow these steps: -Ensure to replace `INSERT_PRIVATE_KEY` with the proper value. 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}. +1. Select the **Create a new file** button in the `contracts` folder. -!!! warning - Never commit or share your private key. Exposed keys can lead to immediate theft of all associated funds. Use environment variables instead. + ![](/images/smart-contracts/dev-environments/remix/get-started/remix-2.webp) -To deploy, run the following command: +2. Name your file with a `.sol` extension, in this case, `Counter.sol`. -```bash -npm run deploy -``` + ![](/images/smart-contracts/dev-environments/remix/get-started/remix-3.webp) -If everything is successful, you will see the address of your deployed contract displayed in the terminal. This address is unique to your contract on the network you defined in the chain configuration, and you'll need it for any future interactions with your contract. +3. Write your Solidity code in the editor. -## Interact with the Contract + You can use the following code as an example: -Create a new file at `src/interact.ts` for interacting with your deployed contract: + ???- "Counter.sol" + + ```solidity + // SPDX-License-Identifier: MIT + pragma solidity ^0.8.0; -```typescript title="src/interact.ts" -import { publicClient } from './createClient'; -import { createWallet } from './createWallet'; -import { readFileSync } from 'fs'; + contract Counter { + int256 private count; -const STORAGE_ABI = JSON.parse( - readFileSync('./artifacts/Storage.json', 'utf8') -); + function increment() public { + count += 1; + } -const interactWithStorage = async ( - contractAddress: `0x${string}`, - privateKey: `0x${string}` -) => { - try { - const wallet = createWallet(privateKey); - const currentNumber = await publicClient.readContract({ - address: contractAddress, - abi: STORAGE_ABI, - functionName: 'storedNumber', - args: [], - }); - console.log(`Stored number: ${currentNumber}`); + function decrement() public { + count -= 1; + } - const newNumber = BigInt(42); - const { request } = await publicClient.simulateContract({ - address: contractAddress, - abi: STORAGE_ABI, - functionName: 'setNumber', - args: [newNumber], - account: wallet.account, - }); + function getCount() public view returns (int256) { + return count; + } + } + ``` - const hash = await wallet.writeContract(request); - await publicClient.waitForTransactionReceipt({ hash }); - console.log(`Number updated to ${newNumber}`); + ![](/images/smart-contracts/dev-environments/remix/get-started/remix-4.webp) - const updatedNumber = await publicClient.readContract({ - address: contractAddress, - abi: STORAGE_ABI, - functionName: 'storedNumber', - args: [], - }); - console.log('Updated stored number:', updatedNumber); - } catch (error) { - console.error('Interaction failed:', error); - } -}; -const PRIVATE_KEY = 'INSERT_PRIVATE_KEY'; -const CONTRACT_ADDRESS = 'INSERT_CONTRACT_ADDRESS'; +## Compiling Your Contract -interactWithStorage(CONTRACT_ADDRESS, PRIVATE_KEY); +1. 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`. -Ensure to replace `INSERT_PRIVATE_KEY` and `INSERT_CONTRACT_ADDRESS` with the proper values. + ![](/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. -To interact with the contract: +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. + 2. The `Counter_metadata.json` and the `Counter.json` files have been generated. -```bash -npm run interact -``` + ![](/images/smart-contracts/dev-environments/remix/get-started/remix-6.webp) -Following a successful interaction, you will see the stored value before and after the transaction. The output will show the initial stored number (0 if you haven't modified it yet), confirm when the transaction to set the number to 42 is complete, and then display the updated stored number value. This demonstrates both reading from and writing to your smart contract. +## Deploying Contracts -## Where to Go Next +1. To deploy your contract, you need to: -Now that you have the foundation for using viem with Polkadot Hub, consider exploring: + 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) -- External __Advanced viem Features__ +2. Enable the **Injected Provider - Talisman** option. - --- - Explore viem's documentation: -
    -
  • [:octicons-arrow-right-24: Multi call](https://viem.sh/docs/contract/multicall#multicall){target=\_blank}
  • + ![](/images/smart-contracts/dev-environments/remix/get-started/remix-8.webp) -
  • [:octicons-arrow-right-24: Batch transactions](https://viem.sh/docs/clients/transports/http#batch-json-rpc){target=\_blank}
  • +4. Click again the **Environment** dropdown and select **Injected Provider - Talisman**. -
  • [:octicons-arrow-right-24: Custom actions](https://viem.sh/docs/clients/custom#extending-with-actions-or-configuration){target=\_blank}
  • -
+ ![](/images/smart-contracts/dev-environments/remix/get-started/remix-9.webp) -- External __Test Frameworks__ +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) - Integrate viem with the following frameworks for comprehensive testing: -
    -
  • [:octicons-arrow-right-24: Hardhat](https://hardhat.org/){target=\_blank}
  • +5. Once your contract is deployed successfully, you will see the following output in the Remix terminal: -
  • [:octicons-arrow-right-24: Foundry](https://getfoundry.sh/){target=\_blank}
  • -
+ ![](/images/smart-contracts/dev-environments/remix/get-started/remix-11.webp) -- External __Event Handling__ +## 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. + +## 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. + +Explore more about smart contracts through these resources: + +
+ +- Guide __Smart Contracts on Polkadot__ --- - Learn how to subscribe to and process contract events: -
    -
  • [:octicons-arrow-right-24: Event subscription](https://viem.sh/docs/actions/public/watchEvent#watchevent){target=\_blank}
  • -
+ Dive into advanced smart contract concepts. -- External __Building dApps__ + [:octicons-arrow-right-24: Get Started](/smart-contracts/) + +- External __OpenZeppelin Contracts__ --- - Combine viem the following technologies to create full-stack applications: -
    -
  • [:octicons-arrow-right-24: Next.js](https://nextjs.org/docs){target=\_blank}
  • + Test your skills by deploying a simple contracts with prebuilt templates. -
  • [:octicons-arrow-right-24: Node.js](https://nodejs.org/en){target=\_blank}
  • -
+ [:octicons-arrow-right-24: Get Started](https://www.openzeppelin.com/solidity-contracts){target=\_blank}
--- -Page Title: Wagmi for Polkadot Hub Smart Contracts +Page Title: viem for Polkadot Hub Smart Contracts -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-wagmi.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/libraries/wagmi/ -- Summary: Learn how to use Wagmi React Hooks to fetch and interact with smart contracts on Polkadot Hub for seamless dApp integration. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-viem.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/libraries/viem/ +- Summary: This guide covers deploying and interacting with contracts on Polkadot Hub using viem, a TypeScript library for Ethereum-compatible chains. -# Wagmi +# viem !!! smartcontract "PolkaVM Preview Release" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction -[Wagmi](https://wagmi.sh/){target=\_blank} is a collection of [React Hooks](https://wagmi.sh/react/api/hooks){target=\_blank} for interacting with Ethereum-compatible blockchains, focusing on developer experience, feature richness, and reliability. +[viem](https://viem.sh/){target=\_blank} is a lightweight TypeScript library designed for interacting with Ethereum-compatible blockchains. This comprehensive guide will walk you through using viem to interact with and deploy smart contracts to Polkadot Hub. -This guide demonstrates how to use Wagmi to interact with and deploy smart contracts to Polkadot Hub, providing a seamless frontend integration for your dApps. +## 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 +viem-project/ +├── package.json +├── tsconfig.json +├── src/ +│ ├── chainConfig.ts +│ ├── createClient.ts +│ ├── createWallet.ts +│ ├── compile.ts +│ ├── deploy.ts +│ └── interact.ts +├── contracts/ +│ └── Storage.sol +└── artifacts/ + ├── Storage.json + └── Storage.polkavm +``` ## Set Up the Project -To start working with Wagmi, create a new React project and initialize it by running the following commands in your terminal: +First, create a new folder and initialize your project: ```bash -# Create a new React project using Next.js -npx create-next-app@latest wagmi-asset-hub -cd wagmi-asset-hub +mkdir viem-project +cd viem-project +npm init -y ``` ## Install Dependencies -Install Wagmi and its peer dependencies: +Install viem along with other necessary dependencies, including [@parity/resolc](https://www.npmjs.com/package/@parity/resolc){target=\_blank}, which enables to compile smart contracts to [PolkaVM](/smart-contracts/for-eth-devs/#polkavm){target=\_blank} bytecode: ```bash -# Install Wagmi and its dependencies -npm install wagmi viem @tanstack/react-query -``` +# Install viem and resolc +npm install viem @parity/resolc -## Configure Wagmi for Polkadot Hub +# Install TypeScript and development dependencies +npm install --save-dev typescript ts-node @types/node +``` -Create a configuration file to initialize Wagmi with Polkadot Hub. In your project, create a file named `src/lib/wagmi.ts` and add the code below. Be sure to replace `INSERT_RPC_URL`, `INSERT_CHAIN_ID`, `INSERT_CHAIN_NAME`, `INSERT_NETWORK_NAME`, `INSERT_CHAIN_DECIMALS`, `INSERT_CURRENCY_NAME`, and `INSERT_CURRENCY_SYMBOL` with your specific values. +## Initialize Project -```typescript title="src/lib/wagmi.ts" -import { http, createConfig } from 'wagmi' +Initialize a TypeScript project by running the following command: + +```bash +npx tsc --init +``` + +Add the following scripts to your `package.json` file to enable running TypeScript files: + +```json +{ + "scripts": { + "client": "ts-node src/createClient.ts", + "compile": "ts-node src/compile.ts", + "deploy": "ts-node src/deploy.ts", + "interact": "ts-node src/interact.ts" + }, +} +``` + +Create a directory for your TypeScript source files: + +```bash +mkdir src +``` + +## Set Up the Chain Configuration + +The first step is to set up the chain configuration. Create a new file at `src/chainConfig.ts`: + +```typescript title="src/chainConfig.ts" +import { http } from 'viem'; + +export const TRANSPORT = http('INSERT_RPC_URL'); // Configure the Polkadot Hub chain -const assetHub = { +export const POLKADOT_HUB = { id: INSERT_CHAIN_ID, name: 'INSERT_CHAIN_NAME', network: 'INSERT_NETWORK_NAME', @@ -10232,25 +10362,57 @@ const assetHub = { }, }, } as const; +``` -// Create Wagmi config -export const config = createConfig({ - chains: [assetHub], - transports: { - [assetHub.id]: http(), +Ensure to replace `INSERT_RPC_URL`, `INSERT_CHAIN_ID`, `INSERT_CHAIN_NAME`, `INSERT_NETWORK_NAME`, `INSERT_CHAIN_DECIMALS`, `INSERT_CURRENCY_NAME`, and `INSERT_CURRENCY_SYMBOL` with the proper values. Check the [Connect to Polkadot](/smart-contracts/connect/){target=\_blank} page for more information on the possible values. + +## Set Up the viem Client + +To interact with the chain, you need to create a client that is used solely for reading data. To accomplish this, create a new file at `src/createClient.ts`: + +```typescript title="src/createClient.ts" +import { createPublicClient, createWalletClient, http } from 'viem'; + +const transport = http('INSERT_RPC_URL'); + +// Configure the Polkadot Hub chain +const assetHub = { + id: INSERT_CHAIN_ID, + name: 'INSERT_CHAIN_NAME', + network: 'INSERT_NETWORK_NAME', + nativeCurrency: { + decimals: INSERT_CHAIN_DECIMALS, + name: 'INSERT_CURRENCY_NAME', + symbol: 'INSERT_CURRENCY_SYMBOL', }, -}) + rpcUrls: { + default: { + http: ['INSERT_RPC_URL'], + }, + }, +} as const; + +// Create a public client for reading data +export const publicClient = createPublicClient({ + chain: assetHub, + transport, +}); + ``` -??? code "Example Polkadot Hub TestNet Configuration" +After setting up the [Public Client](https://viem.sh/docs/clients/public#public-client){target=\_blank}, you can begin querying the blockchain. Here's an example of fetching the latest block number: - ```typescript title="src/lib/wagmi.ts" - import { http, createConfig } from 'wagmi'; +??? code "Fetch Last Block code" + + ```js title="src/fetchLastBlock.ts" + import { createPublicClient, http } from 'viem'; + + const transport = http('https://testnet-passet-hub-eth-rpc.polkadot.io'); // Configure the Polkadot Hub chain - const assetHub = { + const polkadotHubTestnet = { id: 420420422, - name: 'polkadot-hub-testnet', + name: 'Polkadot Hub TestNet', network: 'polkadot-hub-testnet', nativeCurrency: { decimals: 18, @@ -10264,909 +10426,931 @@ export const config = createConfig({ }, } as const; - // Create wagmi config - export const config = createConfig({ - chains: [assetHub], - transports: { - [assetHub.id]: http(), - }, + // Create a public client for reading data + export const publicClient = createPublicClient({ + chain: polkadotHubTestnet, + transport, }); - ``` -## Set Up the Wagmi Provider + const main = async () => { + try { + const block = await publicClient.getBlock(); + console.log('Last block: ' + block.number.toString()); + } catch (error: unknown) { + console.error('Error connecting to Polkadot Hub TestNet: ' + error); + } + }; -To enable Wagmi in your React application, you need to wrap your app with the [`WagmiProvider`](https://wagmi.sh/react/api/WagmiProvider#wagmiprovider){target=\_blank}. Update your `app/layout.tsx` file (for Next.js app router) with the following code: + main(); + ``` -```typescript title="app/layout.tsx" -// For app router (src/app/layout.tsx) -"use client"; +## Set Up a Wallet -import { WagmiProvider } from "wagmi"; -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import { config } from "./lib/wagmi"; +In case you need to sign transactions, you will need to instantiate a [Wallet Client](https://viem.sh/docs/clients/wallet#wallet-client){target=\_blank} object within your project. To do so, create `src/createWallet.ts`: -// Create a query client -const queryClient = new QueryClient(); +```typescript title="src/createWallet.ts" +import { privateKeyToAccount } from 'viem/accounts'; +import { createWalletClient, http } from 'viem'; -export default function RootLayout({ - children, -}: { - children: React.ReactNode; -}) { - return ( - - - - - {children} - - - - - ); -} +const transport = http('INSERT_RPC_URL'); + +// Configure the Polkadot Hub chain +const assetHub = { + id: INSERT_CHAIN_ID, + name: 'INSERT_CHAIN_NAME', + network: 'INSERT_NETWORK_NAME', + nativeCurrency: { + decimals: INSERT_CHAIN_DECIMALS, + name: 'INSERT_CURRENCY_NAME', + symbol: 'INSERT_CURRENCY_SYMBOL', + }, + rpcUrls: { + default: { + http: ['INSERT_RPC_URL'], + }, + public: { + http: ['INSERT_RPC_URL'], + }, + }, +} as const; +// Create a wallet client for writing data +export const createWallet = (privateKey: `0x${string}`) => { + const account = privateKeyToAccount(privateKey); + return createWalletClient({ + account, + chain: assetHub, + transport, + }); +}; ``` !!!note - If you are using a Next.js pages router, you should modify the `src/pages/_app.tsx` instead. + The wallet you import with your private key must have sufficient funds to pay for transaction fees when deploying contracts or interacting with them. Make sure to fund your wallet with the appropriate native tokens for the network you're connecting to. -## Connect a Wallet +## Sample Smart Contract -Create a component to connect wallets to your dApp. Create a file named `app/components/ConnectWallet.tsx`: +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. -```typescript title="app/components/ConnectWallet.tsx" -"use client"; +```bash +mkdir contracts artifacts +``` -import React from "react"; -import { useConnect, useAccount, useDisconnect } from "wagmi"; -import { injected } from "wagmi/connectors"; +You can use the following contract to interact with the blockchain. Paste the following contract in `contracts/Storage.sol`: -export function ConnectWallet() { - const { connect } = useConnect(); - const { address, isConnected } = useAccount(); - const { disconnect } = useDisconnect(); +```solidity title="contracts/Storage.sol" +//SPDX-License-Identifier: MIT - if (isConnected) { - return ( -
-
Connected to {address}
- -
- ); - } +// 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; - return ( - - ); -} +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; + } +} ``` -This component uses the following React hooks: +## Compile the Contract -- **[`useConnect`](https://wagmi.sh/react/api/hooks/useConnect#useconnect){target=\_blank}**: Provides functions and state for connecting the user's wallet to your dApp. The `connect` function initiates the connection flow with the specified connector. -- **[`useDisconnect`](https://wagmi.sh/react/api/hooks/useDisconnect#usedisconnect){target=\_blank}**: Provides a function to disconnect the currently connected wallet. -- **[`useAccount`](https://wagmi.sh/react/api/hooks/useAccount#useaccount){target=\_blank}**: Returns data about the connected account, including the address and connection status. +!!! 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. -## Fetch Blockchain Data + 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. -Wagmi provides various hooks to fetch blockchain data. Here's an example component that demonstrates some of these hooks: +Create a new file at `src/compile.ts` for handling contract compilation: -```typescript title="app/components/BlockchainInfo.tsx" -"use client"; +```typescript title="src/compile.ts" +import { compile } from '@parity/resolc'; +import { readFileSync, writeFileSync } from 'fs'; +import { basename, join } from 'path'; -import { useBlockNumber, useBalance, useAccount } from "wagmi"; +const compileContract = async ( + solidityFilePath: string, + outputDir: string +): Promise => { + try { + // Read the Solidity file + const source: string = readFileSync(solidityFilePath, 'utf8'); -export function BlockchainInfo() { - const { address } = useAccount(); - // Get the latest block number - const { data: blockNumber } = useBlockNumber({ watch: true }); + // Construct the input object for the compiler + const input: Record = { + [basename(solidityFilePath)]: { content: source }, + }; - // Get balance for the connected wallet - const { data: balance } = useBalance({ - address, - }); - - return ( -
-

Blockchain Information

-
-

Current Block: {blockNumber?.toString() || "Loading..."}

- - {address && balance && ( -

- Balance:{" "} - {( - BigInt(balance.value) / BigInt(10 ** balance.decimals) - ).toLocaleString()}{" "} - {balance.symbol} -

- )} -
-
- ); -} - -``` - -This component uses the following React hooks: - -- **[`useBlockNumber`](https://wagmi.sh/react/api/hooks/useBlockNumber#useBlockNumber){target=\_blank}**: Fetches the current block number of the connected chain. The `watch` parameter enables real-time updates when new blocks are mined. -- **[`useBalance`](https://wagmi.sh/react/api/hooks/useBalance#useBalance){target=\_blank}**: Retrieves the native token balance for a specified address, including value, symbol, and decimals information. - -## Interact with Deployed Contract - -This guide uses a simple Storage contract already deployed to the Polkadot Hub TestNet (`0x58053f0e8ede1a47a1af53e43368cd04ddcaf66f`). The code of that contract is: - -??? code "Storage.sol" + console.log(`Compiling contract: ${basename(solidityFilePath)}...`); - ```solidity title="Storage.sol" - //SPDX-License-Identifier: MIT + // Compile the contract + const out = await compile(input); - // 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; + for (const contracts of Object.values(out.contracts)) { + for (const [name, contract] of Object.entries(contracts)) { + console.log(`Compiled contract: ${name}`); - contract Storage { - // Public state variable to store a number - uint256 public storedNumber; + // Write the ABI + const abiPath = join(outputDir, `${name}.json`); + writeFileSync(abiPath, JSON.stringify(contract.abi, null, 2)); + console.log(`ABI saved to ${abiPath}`); - /** - * 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; + // Write the bytecode + if ( + contract.evm && + contract.evm.bytecode && + contract.evm.bytecode.object + ) { + const bytecodePath = join(outputDir, `${name}.polkavm`); + writeFileSync( + bytecodePath, + Buffer.from(contract.evm.bytecode.object, 'hex') + ); + console.log(`Bytecode saved to ${bytecodePath}`); + } else { + console.warn(`No bytecode found for contract: ${name}`); } + } } - ``` + } catch (error) { + console.error('Error compiling contracts:', error); + } +}; -Create a component to interact with your deployed contract. Create a file named `app/components/StorageContract.tsx`: +const solidityFilePath: string = './contracts/Storage.sol'; +const outputDir: string = './artifacts/'; -```typescript title="app/components/StorageContract.tsx" -"use client"; +compileContract(solidityFilePath, outputDir); +``` -import { useState } from "react"; -import { - useReadContract, - useWriteContract, - useWaitForTransactionReceipt, -} from "wagmi"; +To compile your contract: -const CONTRACT_ADDRESS = - "0xabBd46Ef74b88E8B1CDa49BeFb5057710443Fd29" as `0x${string}`; +```bash +npm run compile +``` -export function StorageContract() { - const [number, setNumber] = useState("42"); +After executing this script, you will see the compilation results including the generated `Storage.json` (containing the contract's ABI) and `Storage.polkavm` (containing the compiled bytecode) files in the `artifacts` folder. These files contain all the necessary information for deploying and interacting with your smart contract on Polkadot Hub. - // Contract ABI (should match your compiled contract) - const abi = [ - { - inputs: [], - name: "storedNumber", - outputs: [{ internalType: "uint256", name: "", type: "uint256" }], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { internalType: "uint256", name: "_newNumber", type: "uint256" }, - ], - name: "setNumber", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, - ]; +## Deploy the Contract - // Read the current stored number - const { data: storedNumber, refetch } = useReadContract({ - address: CONTRACT_ADDRESS, - abi, - functionName: "storedNumber", - }); +Create a new file at `src/deploy.ts` for handling contract deployment: - // Write to the contract - const { writeContract, data: hash, error, isPending } = useWriteContract(); +```typescript title="src/deploy.ts" +import { readFileSync } from 'fs'; +import { join } from 'path'; +import { createWallet } from './createWallet'; +import { publicClient } from './createClient'; - // Wait for transaction to be mined - const { isLoading: isConfirming, isSuccess: isConfirmed } = - useWaitForTransactionReceipt({ - hash, - }); +const deployContract = async ( + contractName: string, + privateKey: `0x${string}` +) => { + try { + console.log(`Deploying ${contractName}...`); - const handleSetNumber = () => { - writeContract({ - address: CONTRACT_ADDRESS, + // Read contract artifacts + const abi = JSON.parse( + readFileSync( + join(__dirname, '../artifacts', `${contractName}.json`), + 'utf8' + ) + ); + const bytecode = `0x${readFileSync( + join(__dirname, '../artifacts', `${contractName}.polkavm`) + ).toString('hex')}` as `0x${string}`; + + // Create wallet + const wallet = createWallet(privateKey); + + // Deploy contract + const hash = await wallet.deployContract({ abi, - functionName: "setNumber", - args: [BigInt(number)], + bytecode, + args: [], // Add constructor arguments if needed }); - }; - return ( -
-

Storage Contract Interaction

-
-

Contract Address: {CONTRACT_ADDRESS}

-

Current Stored Number: {storedNumber?.toString() || "Loading..."}

-
+ // Wait for deployment + const receipt = await publicClient.waitForTransactionReceipt({ hash }); + const contractAddress = receipt.contractAddress; -
- setNumber(e.target.value)} - disabled={isPending || isConfirming} - /> - -
+ console.log(`Contract deployed at: ${contractAddress}`); + return contractAddress; + } catch (error) { + console.error('Deployment failed:', error); + throw error; + } +}; - {error &&
Error: {error.message}
} +const privateKey = 'INSERT_PRIVATE_KEY'; +deployContract('Storage', privateKey); +``` - {isConfirmed && ( -
- Successfully updated!{" "} - -
- )} -
- ); -} +Ensure to replace `INSERT_PRIVATE_KEY` with the proper value. 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 commit or share your private key. Exposed keys can lead to immediate theft of all associated funds. Use environment variables instead. +To deploy, run the following command: + +```bash +npm run deploy ``` -This component demonstrates how to interact with a smart contract using Wagmi's hooks: +If everything is successful, you will see the address of your deployed contract displayed in the terminal. This address is unique to your contract on the network you defined in the chain configuration, and you'll need it for any future interactions with your contract. -- **[`useReadContract`](https://wagmi.sh/react/api/hooks/useReadContract#useReadContract){target=\_blank}**: Calls a read-only function on your smart contract to retrieve data without modifying the blockchain state. -- **[`useWriteContract`](https://wagmi.sh/react/api/hooks/useWriteContract#useWriteContract){target=\_blank}**: Calls a state-modifying function on your smart contract, which requires a transaction to be signed and sent. -- **[`useWaitForTransactionReceipt`](https://wagmi.sh/react/api/hooks/useWaitForTransactionReceipt#useWaitForTransactionReceipt){target=\_blank}**: Tracks the status of a transaction after it's been submitted, allowing you to know when it's been confirmed. +## Interact with the Contract -The component also includes proper state handling to: +Create a new file at `src/interact.ts` for interacting with your deployed contract: -- Show the current value stored in the contract. -- Allow users to input a new value. -- Display transaction status (pending, confirming, or completed). -- Handle errors. -- Provide feedback when a transaction is successful. +```typescript title="src/interact.ts" +import { publicClient } from './createClient'; +import { createWallet } from './createWallet'; +import { readFileSync } from 'fs'; -## Integrate Components +const STORAGE_ABI = JSON.parse( + readFileSync('./artifacts/Storage.json', 'utf8') +); -Update your main page to combine all the components. Create or update the file `src/app/page.tsx`: +const interactWithStorage = async ( + contractAddress: `0x${string}`, + privateKey: `0x${string}` +) => { + try { + const wallet = createWallet(privateKey); + const currentNumber = await publicClient.readContract({ + address: contractAddress, + abi: STORAGE_ABI, + functionName: 'storedNumber', + args: [], + }); + console.log(`Stored number: ${currentNumber}`); -```typescript title="src/app/page.tsx" -"use client"; + const newNumber = BigInt(42); + const { request } = await publicClient.simulateContract({ + address: contractAddress, + abi: STORAGE_ABI, + functionName: 'setNumber', + args: [newNumber], + account: wallet.account, + }); -import { BlockchainInfo } from "./components/BlockchainInfo"; -import { ConnectWallet } from "./components/ConnectWallet"; -import { StorageContract } from "./components/StorageContract"; -import { useAccount } from "wagmi"; + const hash = await wallet.writeContract(request); + await publicClient.waitForTransactionReceipt({ hash }); + console.log(`Number updated to ${newNumber}`); -export default function Home() { - const { isConnected } = useAccount(); + const updatedNumber = await publicClient.readContract({ + address: contractAddress, + abi: STORAGE_ABI, + functionName: 'storedNumber', + args: [], + }); + console.log('Updated stored number:', updatedNumber); + } catch (error) { + console.error('Interaction failed:', error); + } +}; - return ( -
-

Wagmi - Polkadot Hub Smart Contracts

- - {isConnected ? : Connect your wallet} - {isConnected ? : Connect your wallet} -
- ); -} +const PRIVATE_KEY = 'INSERT_PRIVATE_KEY'; +const CONTRACT_ADDRESS = 'INSERT_CONTRACT_ADDRESS'; +interactWithStorage(CONTRACT_ADDRESS, PRIVATE_KEY); + +``` + +Ensure to replace `INSERT_PRIVATE_KEY` and `INSERT_CONTRACT_ADDRESS` with the proper values. + +To interact with the contract: + +```bash +npm run interact ``` +Following a successful interaction, you will see the stored value before and after the transaction. The output will show the initial stored number (0 if you haven't modified it yet), confirm when the transaction to set the number to 42 is complete, and then display the updated stored number value. This demonstrates both reading from and writing to your smart contract. + ## Where to Go Next -Now that you have the foundational knowledge to use Wagmi with Polkadot Hub, consider exploring: +Now that you have the foundation for using viem with Polkadot Hub, consider exploring:
-- External __Advanced Wagmi__ +- External __Advanced viem Features__ --- + Explore viem's documentation: +
    +
  • [:octicons-arrow-right-24: Multi call](https://viem.sh/docs/contract/multicall#multicall){target=\_blank}
  • - Explore Wagmi's advanced features: +
  • [:octicons-arrow-right-24: Batch transactions](https://viem.sh/docs/clients/transports/http#batch-json-rpc){target=\_blank}
  • -
      -
    • [:octicons-arrow-right-24: Watch Contract Events](https://wagmi.sh/core/api/actions/watchContractEvent#eventname){target=\_blank}
    • -
    • [:octicons-arrow-right-24: Different Transports](https://wagmi.sh/react/api/transports){target=\_blank}
    • -
    • [:octicons-arrow-right-24: Actions](https://wagmi.sh/react/api/actions){target=\_blank}
    • +
    • [:octicons-arrow-right-24: Custom actions](https://viem.sh/docs/clients/custom#extending-with-actions-or-configuration){target=\_blank}
    -- External __Wallet Integration__ +- External __Test Frameworks__ --- - Connect your dApp with popular wallet providers: - + Integrate viem with the following frameworks for comprehensive testing:
      -
    • [:octicons-arrow-right-24: MetaMask](https://wagmi.sh/core/api/connectors/metaMask){target=\_blank}
    • -
    • [:octicons-arrow-right-24: WalletConnect](https://wagmi.sh/core/api/connectors/walletConnect){target=\_blank}
    • -
    • [:octicons-arrow-right-24: Coinbase Wallet](https://wagmi.sh/core/api/connectors/coinbaseWallet){target=\_blank}
    • +
    • [:octicons-arrow-right-24: Hardhat](https://hardhat.org/){target=\_blank}
    • + +
    • [:octicons-arrow-right-24: Foundry](https://getfoundry.sh/){target=\_blank}
    -- External __Testing & Development__ +- External __Event Handling__ --- - Enhance your development workflow: + Learn how to subscribe to and process contract events: +
      +
    • [:octicons-arrow-right-24: Event subscription](https://viem.sh/docs/actions/public/watchEvent#watchevent){target=\_blank}
    • +
    + +- External __Building dApps__ + + --- + Combine viem the following technologies to create full-stack applications:
      -
    • [:octicons-arrow-right-24: Test Suite](https://wagmi.sh/dev/contributing#_6-running-the-test-suite){target=\_blank}
    • -
    • [:octicons-arrow-right-24: Dev Playground](https://wagmi.sh/dev/contributing#_5-running-the-dev-playgrounds){target=\_blank}
    • +
    • [:octicons-arrow-right-24: Next.js](https://nextjs.org/docs){target=\_blank}
    • + +
    • [:octicons-arrow-right-24: Node.js](https://nodejs.org/en){target=\_blank}
    +
--- -Page Title: Wallets for Polkadot Hub +Page Title: Wagmi for Polkadot Hub Smart Contracts -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-wallets.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/integrations/wallets/ -- Summary: Comprehensive guide to connecting and managing wallets for Polkadot Hub, covering step-by-step instructions for interacting with the ecosystem. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-wagmi.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/libraries/wagmi/ +- Summary: Learn how to use Wagmi React Hooks to fetch and interact with smart contracts on Polkadot Hub for seamless dApp integration. -# Wallets for Polkadot Hub +# Wagmi !!! 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. - -## Connect Your Wallet - -### MetaMask - -[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. - -To 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. - -For example, to connect to the Polkadot Hub TestNet via MetaMask, you need to follow these steps: - -1. Open the MetaMask extension and click on the network icon to switch to the Polkadot Hub TestNet. - - ![](/images/smart-contracts/integrations/wallets/wallets-1.webp){: .browser-extension} - -2. Click on the **Add a custom network** button. - - ![](/images/smart-contracts/integrations/wallets/wallets-2.webp){: .browser-extension} - -3. 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). +[Wagmi](https://wagmi.sh/){target=\_blank} is a collection of [React Hooks](https://wagmi.sh/react/api/hooks){target=\_blank} for interacting with Ethereum-compatible blockchains, focusing on developer experience, feature richness, and reliability. - ![](/images/smart-contracts/integrations/wallets/wallets-3.webp){: .browser-extension} +This guide demonstrates how to use Wagmi to interact with and deploy smart contracts to Polkadot Hub, providing a seamless frontend integration for your dApps. -4. Click on **Polkadot Hub TestNet** to switch the network. +## Set Up the Project - ![](/images/smart-contracts/integrations/wallets/wallets-4.webp){: .browser-extension} +To start working with Wagmi, create a new React project and initialize it by running the following commands in your terminal: -The steps in the preceding section can be used to connect to any chain by modifying the network specification and endpoint parameters. +```bash +# Create a new React project using Next.js +npx create-next-app@latest wagmi-asset-hub +cd wagmi-asset-hub +``` -### SubWallet +## Install Dependencies -[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. +Install Wagmi and its peer dependencies: -SubWallet 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. +```bash +# Install Wagmi and its dependencies +npm install wagmi viem @tanstack/react-query +``` -You 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). +## Configure Wagmi for Polkadot Hub -??? code "Polkadot Hub TestNet" - 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. - The ETH RPC endpoint will let you send transactions that follow an ETH format, while the Substrate endpoint will follow a Substrate transaction format. - Note the PAS token, which is the native token of the Polkadot Hub TestNet. +Create a configuration file to initialize Wagmi with Polkadot Hub. In your project, create a file named `src/lib/wagmi.ts` and add the code below. Be sure to replace `INSERT_RPC_URL`, `INSERT_CHAIN_ID`, `INSERT_CHAIN_NAME`, `INSERT_NETWORK_NAME`, `INSERT_CHAIN_DECIMALS`, `INSERT_CURRENCY_NAME`, and `INSERT_CURRENCY_SYMBOL` with your specific values. - ![](/images/smart-contracts/integrations/wallets/subwallet-PAS.webp){: .browser-extension} +```typescript title="src/lib/wagmi.ts" +import { http, createConfig } from 'wagmi' -To connect to Polkadot Hub TestNet using SubWallet, follow these steps: +// Configure the Polkadot Hub chain +const assetHub = { + id: INSERT_CHAIN_ID, + name: 'INSERT_CHAIN_NAME', + network: 'INSERT_NETWORK_NAME', + nativeCurrency: { + decimals: INSERT_CHAIN_DECIMALS, + name: 'INSERT_CURRENCY_NAME', + symbol: 'INSERT_CURRENCY_SYMBOL', + }, + rpcUrls: { + default: { + http: ['INSERT_RPC_URL'], + }, + }, +} as const; -1. 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. +// Create Wagmi config +export const config = createConfig({ + chains: [assetHub], + transports: { + [assetHub.id]: http(), + }, +}) +``` -2. After setting up your wallet, click the List icon at the top left corner of the extension window to open **Settings**. +??? code "Example Polkadot Hub TestNet Configuration" - ![](/images/smart-contracts/integrations/wallets/subwallet-01.webp){: .browser-extension} + ```typescript title="src/lib/wagmi.ts" + import { http, createConfig } from 'wagmi'; -3. Scroll down and select **Manage networks**. + // Configure the Polkadot Hub chain + const assetHub = { + id: 420420422, + name: 'polkadot-hub-testnet', + network: 'polkadot-hub-testnet', + nativeCurrency: { + decimals: 18, + name: 'PAS', + symbol: 'PAS', + }, + rpcUrls: { + default: { + http: ['https://testnet-passet-hub-eth-rpc.polkadot.io'], + }, + }, + } as const; - ![](/images/smart-contracts/integrations/wallets/subwallet-02.webp){: .browser-extension} + // Create wagmi config + export const config = createConfig({ + chains: [assetHub], + transports: { + [assetHub.id]: http(), + }, + }); + ``` -4. 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. +## Set Up the Wagmi Provider - ![](/images/smart-contracts/integrations/wallets/subwallet-03.webp){: .browser-extension} +To enable Wagmi in your React application, you need to wrap your app with the [`WagmiProvider`](https://wagmi.sh/react/api/WagmiProvider#wagmiprovider){target=\_blank}. Update your `app/layout.tsx` file (for Next.js app router) with the following code: - You are now ready to use SubWallet to interact with [Polkadot Hub TestNet](/smart-contracts/connect/#networks-details){target=\_blank} seamlessly! +```typescript title="app/layout.tsx" +// For app router (src/app/layout.tsx) +"use client"; -![](/images/smart-contracts/integrations/wallets/subwallet-04.webp){: .browser-extension} +import { WagmiProvider } from "wagmi"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { config } from "./lib/wagmi"; -### Talisman +// Create a query client +const queryClient = new QueryClient(); -[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. +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + + + + {children} + + + + + ); +} -To use Talisman with Polkadot Hub TestNet: +``` -1. Install the [Talisman extension](https://talisman.xyz/download){target=\_blank} and set up your wallet by following the on-screen instructions. +!!!note + If you are using a Next.js pages router, you should modify the `src/pages/_app.tsx` instead. -2. Once installed, click on the Talisman icon in your browser extensions and click on the **Settings** button. +## Connect a Wallet - ![](/images/smart-contracts/integrations/wallets/wallets-5.webp){: .browser-extension} +Create a component to connect wallets to your dApp. Create a file named `app/components/ConnectWallet.tsx`: -3. Click the button **All settings**. +```typescript title="app/components/ConnectWallet.tsx" +"use client"; - ![](/images/smart-contracts/integrations/wallets/wallets-6.webp){: .browser-extension} +import React from "react"; +import { useConnect, useAccount, useDisconnect } from "wagmi"; +import { injected } from "wagmi/connectors"; -4. Go to the **Networks & Tokens** section. +export function ConnectWallet() { + const { connect } = useConnect(); + const { address, isConnected } = useAccount(); + const { disconnect } = useDisconnect(); - ![](/images/smart-contracts/integrations/wallets/wallets-7.webp) + if (isConnected) { + return ( +
+
Connected to {address}
+ +
+ ); + } -5. Click the **Manage networks** button. + return ( + + ); +} - ![](/images/smart-contracts/integrations/wallets/wallets-8.webp) +``` -6. Click the **+ Add network** button. +This component uses the following React hooks: - ![](/images/smart-contracts/integrations/wallets/wallets-9.webp) +- **[`useConnect`](https://wagmi.sh/react/api/hooks/useConnect#useconnect){target=\_blank}**: Provides functions and state for connecting the user's wallet to your dApp. The `connect` function initiates the connection flow with the specified connector. +- **[`useDisconnect`](https://wagmi.sh/react/api/hooks/useDisconnect#usedisconnect){target=\_blank}**: Provides a function to disconnect the currently connected wallet. +- **[`useAccount`](https://wagmi.sh/react/api/hooks/useAccount#useaccount){target=\_blank}**: Returns data about the connected account, including the address and connection status. -7. Fill in the form with the required parameters and click the **Add network** button. +## Fetch Blockchain Data - ![](/images/smart-contracts/integrations/wallets/wallets-10.webp) +Wagmi provides various hooks to fetch blockchain data. Here's an example component that demonstrates some of these hooks: -8. After that, you can switch to the Polkadot Hub TestNet by clicking on the network icon and selecting **Polkadot Hub TestNet**. +```typescript title="app/components/BlockchainInfo.tsx" +"use client"; - ![](/images/smart-contracts/integrations/wallets/wallets-11.webp) +import { useBlockNumber, useBalance, useAccount } from "wagmi"; -After 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. +export function BlockchainInfo() { + const { address } = useAccount(); + // Get the latest block number + const { data: blockNumber } = useBlockNumber({ watch: true }); + // Get balance for the connected wallet + const { data: balance } = useBalance({ + address, + }); -## Conclusion + return ( +
+

Blockchain Information

+
+

Current Block: {blockNumber?.toString() || "Loading..."}

-Choosing 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. + {address && balance && ( +

+ Balance:{" "} + {( + BigInt(balance.value) / BigInt(10 ** balance.decimals) + ).toLocaleString()}{" "} + {balance.symbol} +

+ )} +
+
+ ); +} -!!!info - Remember to always verify network parameters when connecting to ensure a secure and reliable connection to the Polkadot ecosystem. +``` +This component uses the following React hooks: ---- +- **[`useBlockNumber`](https://wagmi.sh/react/api/hooks/useBlockNumber#useBlockNumber){target=\_blank}**: Fetches the current block number of the connected chain. The `watch` parameter enables real-time updates when new blocks are mined. +- **[`useBalance`](https://wagmi.sh/react/api/hooks/useBalance#useBalance){target=\_blank}**: Retrieves the native token balance for a specified address, including value, symbol, and decimals information. -Page Title: Web3.js +## Interact with Deployed Contract -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-web3-js.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/libraries/web3-js/ -- Summary: Learn how to interact with Polkadot Hub using Web3.js, deploying Solidity contracts, and interacting with deployed smart contracts. +This guide uses a simple Storage contract already deployed to the Polkadot Hub TestNet (`0x58053f0e8ede1a47a1af53e43368cd04ddcaf66f`). The code of that contract is: -# Web3.js +??? code "Storage.sol" -!!! 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. + ```solidity title="Storage.sol" + //SPDX-License-Identifier: MIT -## Introduction + // 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; -Interacting with blockchains typically requires an interface between your application and the network. [Web3.js](https://web3js.readthedocs.io/){target=\_blank} offers this interface through a comprehensive collection of libraries, facilitating seamless interaction with the nodes using HTTP or WebSocket protocols. This guide illustrates how to utilize Web3.js specifically for interactions with Polkadot Hub. + contract Storage { + // Public state variable to store a number + uint256 public storedNumber; -This guide is intended for developers who are familiar with JavaScript and want to interact with the Polkadot Hub using Web3.js. + /** + * 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; + } + } + ``` -## Prerequisites +Create a component to interact with your deployed contract. Create a file named `app/components/StorageContract.tsx`: -Before getting started, ensure you have the following installed: +```typescript title="app/components/StorageContract.tsx" +"use client"; -- **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. +import { useState } from "react"; +import { + useReadContract, + useWriteContract, + useWaitForTransactionReceipt, +} from "wagmi"; -## Project Structure +const CONTRACT_ADDRESS = + "0xabBd46Ef74b88E8B1CDa49BeFb5057710443Fd29" as `0x${string}`; -This project organizes contracts, scripts, and compiled artifacts for easy development and deployment. +export function StorageContract() { + const [number, setNumber] = useState("42"); -```text title="Web3.js Polkadot Hub" -web3js-project -├── contracts -│ ├── Storage.sol -├── scripts -│ ├── connectToProvider.js -│ ├── fetchLastBlock.js -│ ├── compile.js -│ ├── deploy.js -│ ├── updateStorage.js -├── abis -│ ├── Storage.json -├── artifacts -│ ├── Storage.polkavm -├── node_modules/ -├── package.json -├── package-lock.json -└── README.md -``` + // Contract ABI (should match your compiled contract) + const abi = [ + { + inputs: [], + name: "storedNumber", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "_newNumber", type: "uint256" }, + ], + name: "setNumber", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + ]; -## Set Up the Project + // Read the current stored number + const { data: storedNumber, refetch } = useReadContract({ + address: CONTRACT_ADDRESS, + abi, + functionName: "storedNumber", + }); -To start working with Web3.js, begin by initializing your project: + // Write to the contract + const { writeContract, data: hash, error, isPending } = useWriteContract(); -```bash -npm init -y -``` + // Wait for transaction to be mined + const { isLoading: isConfirming, isSuccess: isConfirmed } = + useWaitForTransactionReceipt({ + hash, + }); -## Install Dependencies + const handleSetNumber = () => { + writeContract({ + address: CONTRACT_ADDRESS, + abi, + functionName: "setNumber", + args: [BigInt(number)], + }); + }; -Next, install the Web3.js library: + return ( +
+

Storage Contract Interaction

+
+

Contract Address: {CONTRACT_ADDRESS}

+

Current Stored Number: {storedNumber?.toString() || "Loading..."}

+
-```bash -npm install web3 -``` +
+ setNumber(e.target.value)} + disabled={isPending || isConfirming} + /> + +
-This guide uses `web3` version `4.16.0`. + {error &&
Error: {error.message}
} -## Set Up the Web3 Provider + {isConfirmed && ( +
+ Successfully updated!{" "} + +
+ )} +
+ ); +} -The provider configuration is the foundation of any Web3.js application. The following example establishes a connection to Polkadot Hub. To use the example script, replace `INSERT_RPC_URL`, `INSERT_CHAIN_ID`, and `INSERT_CHAIN_NAME` with the appropriate values. The provider connection script should look something like this: +``` -```javascript title="scripts/connectToProvider.js" -const { Web3 } = require('web3'); +This component demonstrates how to interact with a smart contract using Wagmi's hooks: -const createProvider = (rpcUrl) => { - const web3 = new Web3(rpcUrl); - return web3; -}; +- **[`useReadContract`](https://wagmi.sh/react/api/hooks/useReadContract#useReadContract){target=\_blank}**: Calls a read-only function on your smart contract to retrieve data without modifying the blockchain state. +- **[`useWriteContract`](https://wagmi.sh/react/api/hooks/useWriteContract#useWriteContract){target=\_blank}**: Calls a state-modifying function on your smart contract, which requires a transaction to be signed and sent. +- **[`useWaitForTransactionReceipt`](https://wagmi.sh/react/api/hooks/useWaitForTransactionReceipt#useWaitForTransactionReceipt){target=\_blank}**: Tracks the status of a transaction after it's been submitted, allowing you to know when it's been confirmed. -const PROVIDER_RPC = { - rpc: 'INSERT_RPC_URL', - chainId: 'INSERT_CHAIN_ID', - name: 'INSERT_CHAIN_NAME', -}; +The component also includes proper state handling to: -createProvider(PROVIDER_RPC.rpc); +- Show the current value stored in the contract. +- Allow users to input a new value. +- Display transaction status (pending, confirming, or completed). +- Handle errors. +- Provide feedback when a transaction is successful. -``` +## Integrate Components -For example, for the Polkadot Hub TestNet, use these specific connection parameters: +Update your main page to combine all the components. Create or update the file `src/app/page.tsx`: -```js -const PROVIDER_RPC = { - rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', - chainId: 420420422, - name: 'polkadot-hub-testnet' -}; -``` +```typescript title="src/app/page.tsx" +"use client"; -With the Web3 provider set up, you can start querying the blockchain. +import { BlockchainInfo } from "./components/BlockchainInfo"; +import { ConnectWallet } from "./components/ConnectWallet"; +import { StorageContract } from "./components/StorageContract"; +import { useAccount } from "wagmi"; -For instance, to fetch the latest block number of the chain, you can use the following code snippet: +export default function Home() { + const { isConnected } = useAccount(); -???+ code "View complete script" + return ( +
+

Wagmi - Polkadot Hub Smart Contracts

+ + {isConnected ? : Connect your wallet} + {isConnected ? : Connect your wallet} +
+ ); +} - ```javascript title="scripts/fetchLastBlock.js" - const { Web3 } = require('web3'); +``` - const createProvider = (rpcUrl) => { - const web3 = new Web3(rpcUrl); - return web3; - }; +## Where to Go Next - const PROVIDER_RPC = { - rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', - chainId: 420420422, - name: 'polkadot-hub-testnet', - }; +Now that you have the foundational knowledge to use Wagmi with Polkadot Hub, consider exploring: - const main = async () => { - try { - const web3 = createProvider(PROVIDER_RPC.rpc); - const latestBlock = await web3.eth.getBlockNumber(); - console.log('Last block: ' + latestBlock); - } catch (error) { - console.error('Error connecting to Polkadot Hub TestNet: ' + error.message); - } - }; +
- main(); +- External __Advanced Wagmi__ - ``` + --- -## Compile Contracts + Explore Wagmi's advanced features: -!!! 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. +
    +
  • [:octicons-arrow-right-24: Watch Contract Events](https://wagmi.sh/core/api/actions/watchContractEvent#eventname){target=\_blank}
  • +
  • [:octicons-arrow-right-24: Different Transports](https://wagmi.sh/react/api/transports){target=\_blank}
  • +
  • [:octicons-arrow-right-24: Actions](https://wagmi.sh/react/api/actions){target=\_blank}
  • +
- 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. +- External __Wallet Integration__ -Polkadot Hub requires contracts to be compiled to [PolkaVM](/smart-contracts/for-eth-devs/dual-vm-stack/){target=\_blank} bytecode. This is achieved using the [`revive`](https://github.com/paritytech/revive/tree/v0.2.0/js/resolc){target=\_blank} compiler. Install the [`@parity/resolc`](https://github.com/paritytech/revive){target=\_blank} library as a development dependency: + --- -```bash -npm install --save-dev @parity/resolc -``` + Connect your dApp with popular wallet providers: -This guide uses `@parity/resolc` version `0.2.0`. +
    +
  • [:octicons-arrow-right-24: MetaMask](https://wagmi.sh/core/api/connectors/metaMask){target=\_blank}
  • +
  • [:octicons-arrow-right-24: WalletConnect](https://wagmi.sh/core/api/connectors/walletConnect){target=\_blank}
  • +
  • [:octicons-arrow-right-24: Coinbase Wallet](https://wagmi.sh/core/api/connectors/coinbaseWallet){target=\_blank}
  • +
-Here's a simple storage contract that you can use to follow the process: +- External __Testing & Development__ -```solidity title="contracts/Storage.sol" -//SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; + --- -contract Storage { - // Public state variable to store a number - uint256 public storedNumber; + Enhance your development workflow: - /** - * 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; - } -} -``` +
    +
  • [:octicons-arrow-right-24: Test Suite](https://wagmi.sh/dev/contributing#_6-running-the-test-suite){target=\_blank}
  • +
  • [:octicons-arrow-right-24: Dev Playground](https://wagmi.sh/dev/contributing#_5-running-the-dev-playgrounds){target=\_blank}
  • +
+
-With that, you can now create a `compile.js` snippet that transforms your solidity code into PolkaVM bytecode: -```javascript 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'); +Page Title: Wallets for Polkadot Hub - // Construct the input object for the compiler - const input = { - [basename(solidityFilePath)]: { content: source }, - }; +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-wallets.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/integrations/wallets/ +- Summary: Comprehensive guide to connecting and managing wallets for Polkadot Hub, covering step-by-step instructions for interacting with the ecosystem. - console.log(`Compiling contract: ${basename(solidityFilePath)}...`); +# Wallets for Polkadot Hub - // Compile the contract - const out = await compile(input); +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. +## Introduction - for (const contracts of Object.values(out.contracts)) { - for (const [name, contract] of Object.entries(contracts)) { - console.log(`Compiled contract: ${name}`); +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. - // Write the ABI - const abiPath = join(outputDir, `${name}.json`); - writeFileSync(abiPath, JSON.stringify(contract.abi, null, 2)); - console.log(`ABI saved to ${abiPath}`); +## Connect Your Wallet - // 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); - } -}; +### MetaMask -const solidityFilePath = './Storage.sol'; -const outputDir = '.'; +[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. -compileContract(solidityFilePath, outputDir); +To 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. -``` +For example, to connect to the Polkadot Hub TestNet via MetaMask, you need to follow these steps: -To compile your contract, simply run the following command: +1. Open the MetaMask extension and click on the network icon to switch to the Polkadot Hub TestNet. -```bash -node compile -``` + ![](/images/smart-contracts/integrations/wallets/wallets-1.webp){: .browser-extension} -After compilation, you'll have two key files: an ABI (`.json`) file, which provides a JSON interface describing the contract's functions and how to interact with it, and a bytecode (`.polkavm`) file, which contains the low-level machine code executable on PolkaVM that represents the compiled smart contract ready for blockchain deployment. +2. Click on the **Add a custom network** button. -## Contract Deployment + ![](/images/smart-contracts/integrations/wallets/wallets-2.webp){: .browser-extension} -To deploy your compiled contract to Polkadot Hub using Web3.js, you'll need an account with a private key to sign the deployment transaction. The deployment process is exactly the same as for any Ethereum-compatible chain, involving creating a contract instance, estimating gas, and sending a deployment transaction. Here's how to deploy the contract, ensure replacing the `INSERT_RPC_URL`, `INSERT_PRIVATE_KEY`, and `INSERT_CONTRACT_NAME` with the appropriate values: +3. 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). -```javascript title="scripts/deploy.js" -import { readFileSync } from 'fs'; -import { Web3 } from 'web3'; + ![](/images/smart-contracts/integrations/wallets/wallets-3.webp){: .browser-extension} -const getAbi = (contractName) => { - try { - return JSON.parse(readFileSync(`${contractName}.json`), 'utf8'); - } catch (error) { - console.error( - `❌ Could not find ABI for contract ${contractName}:`, - error.message - ); - throw error; - } -}; +4. Click on **Polkadot Hub TestNet** to switch the network. -const getByteCode = (contractName) => { - try { - return `0x${readFileSync(`${contractName}.polkavm`).toString('hex')}`; - } catch (error) { - console.error( - `❌ Could not find bytecode for contract ${contractName}:`, - error.message - ); - throw error; - } -}; + ![](/images/smart-contracts/integrations/wallets/wallets-4.webp){: .browser-extension} -export const deploy = async (config) => { - try { - // Initialize Web3 with RPC URL - const web3 = new Web3(config.rpcUrl); +The steps in the preceding section can be used to connect to any chain by modifying the network specification and endpoint parameters. - // Prepare account - const account = web3.eth.accounts.privateKeyToAccount(config.privateKey); - web3.eth.accounts.wallet.add(account); +### SubWallet - // Load abi - const abi = getAbi('Storage'); +[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. - // Create contract instance - const contract = new web3.eth.Contract(abi); +SubWallet 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. - // Prepare deployment - const deployTransaction = contract.deploy({ - data: getByteCode('Storage'), - arguments: [], // Add constructor arguments if needed - }); +You 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). - // Estimate gas - const gasEstimate = await deployTransaction.estimateGas({ - from: account.address, - }); +??? code "Polkadot Hub TestNet" + 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. + The ETH RPC endpoint will let you send transactions that follow an ETH format, while the Substrate endpoint will follow a Substrate transaction format. + Note the PAS token, which is the native token of the Polkadot Hub TestNet. - // Get current gas price - const gasPrice = await web3.eth.getGasPrice(); + ![](/images/smart-contracts/integrations/wallets/subwallet-PAS.webp){: .browser-extension} - // Send deployment transaction - const deployedContract = await deployTransaction.send({ - from: account.address, - gas: gasEstimate, - gasPrice: gasPrice, - }); +To connect to Polkadot Hub TestNet using SubWallet, follow these steps: - // Log and return contract details - console.log(`Contract deployed at: ${deployedContract.options.address}`); - return deployedContract; - } catch (error) { - console.error('Deployment failed:', error); - throw error; - } -}; +1. 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. -// Example usage -const deploymentConfig = { - rpcUrl: 'INSERT_RPC_URL', - privateKey: 'INSERT_PRIVATE_KEY', - contractName: 'INSERT_CONTRACT_NAME', -}; +2. After setting up your wallet, click the List icon at the top left corner of the extension window to open **Settings**. -deploy(deploymentConfig) - .then((contract) => console.log('Deployment successful')) - .catch((error) => console.error('Deployment error')); + ![](/images/smart-contracts/integrations/wallets/subwallet-01.webp){: .browser-extension} -``` +3. Scroll down and select **Manage networks**. -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}. + ![](/images/smart-contracts/integrations/wallets/subwallet-02.webp){: .browser-extension} -To deploy your contract, run the following command: +4. 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. -```bash -node deploy -``` + ![](/images/smart-contracts/integrations/wallets/subwallet-03.webp){: .browser-extension} -## Interact with the Contract + You are now ready to use SubWallet to interact with [Polkadot Hub TestNet](/smart-contracts/connect/#networks-details){target=\_blank} seamlessly! -Once deployed, you can interact with your contract using Web3.js methods. Here's how to set a number and read it back, ensure replacing `INSERT_RPC_URL`, `INSERT_PRIVATE_KEY`, and `INSERT_CONTRACT_ADDRESS` with the appropriate values: +![](/images/smart-contracts/integrations/wallets/subwallet-04.webp){: .browser-extension} -```javascript title="scripts/updateStorage.js" -import { readFileSync } from 'fs'; -import { Web3 } from 'web3'; +### Talisman -const getAbi = (contractName) => { - try { - return JSON.parse(readFileSync(`${contractName}.json`), 'utf8'); - } catch (error) { - console.error( - `❌ Could not find ABI for contract ${contractName}:`, - error.message - ); - throw error; - } -}; +[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. -const updateStorage = async (config) => { - try { - // Initialize Web3 with RPC URL - const web3 = new Web3(config.rpcUrl); +To use Talisman with Polkadot Hub TestNet: - // Prepare account - const account = web3.eth.accounts.privateKeyToAccount(config.privateKey); - web3.eth.accounts.wallet.add(account); +1. Install the [Talisman extension](https://talisman.xyz/download){target=\_blank} and set up your wallet by following the on-screen instructions. - // Load abi - const abi = getAbi('Storage'); +2. Once installed, click on the Talisman icon in your browser extensions and click on the **Settings** button. - // Create contract instance - const contract = new web3.eth.Contract(abi, config.contractAddress); + ![](/images/smart-contracts/integrations/wallets/wallets-5.webp){: .browser-extension} - // Get initial value - const initialValue = await contract.methods.storedNumber().call(); - console.log('Current stored value:', initialValue); +3. Click the button **All settings**. - // Prepare transaction - const updateTransaction = contract.methods.setNumber(1); + ![](/images/smart-contracts/integrations/wallets/wallets-6.webp){: .browser-extension} - // Estimate gas - const gasEstimate = await updateTransaction.estimateGas({ - from: account.address, - }); +4. Go to the **Networks & Tokens** section. - // Get current gas price - const gasPrice = await web3.eth.getGasPrice(); + ![](/images/smart-contracts/integrations/wallets/wallets-7.webp) - // Send update transaction - const receipt = await updateTransaction.send({ - from: account.address, - gas: gasEstimate, - gasPrice: gasPrice, - }); +5. Click the **Manage networks** button. - // Log transaction details - console.log(`Transaction hash: ${receipt.transactionHash}`); + ![](/images/smart-contracts/integrations/wallets/wallets-8.webp) - // Get updated value - const newValue = await contract.methods.storedNumber().call(); - console.log('New stored value:', newValue); +6. Click the **+ Add network** button. - return receipt; - } catch (error) { - console.error('Update failed:', error); - throw error; - } -}; + ![](/images/smart-contracts/integrations/wallets/wallets-9.webp) -// Example usage -const config = { - rpcUrl: 'INSERT_RPC_URL', - privateKey: 'INSERT_PRIVATE_KEY', - contractAddress: 'INSERT_CONTRACT_ADDRESS', -}; +7. Fill in the form with the required parameters and click the **Add network** button. -updateStorage(config) - .then((receipt) => console.log('Update successful')) - .catch((error) => console.error('Update error')); + ![](/images/smart-contracts/integrations/wallets/wallets-10.webp) -``` +8. After that, you can switch to the Polkadot Hub TestNet by clicking on the network icon and selecting **Polkadot Hub TestNet**. -To execute the logic above, run: + ![](/images/smart-contracts/integrations/wallets/wallets-11.webp) -```bash -node updateStorage -``` +After 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. -## Where to Go Next -Now that you’ve learned how to use Web3.js with Polkadot Hub, explore more advanced topics: +## Conclusion + +Choosing 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. -- **Utilize Web3.js utilities**: Learn about additional [Web3.js](https://docs.web3js.org/){target=\_blank} features such as signing transactions, managing wallets, and subscribing to events. -- **Build full-stack dApps**: [integrate Web3.js](https://docs.web3js.org/guides/dapps/intermediate-dapp){target=\_blank} with different libraries and frameworks to build decentralized web applications. +!!!info + Remember to always verify network parameters when connecting to ensure a secure and reliable connection to the Polkadot ecosystem. --- diff --git a/.ai/categories/tooling.md b/.ai/categories/tooling.md index d5f748831..42d9674c5 100644 --- a/.ai/categories/tooling.md +++ b/.ai/categories/tooling.md @@ -2976,6 +2976,621 @@ 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 to Polkadot Hub with Web3.js + +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-web3-js.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/libraries/web3-js/ +- Summary: Learn how to interact with Polkadot Hub using Web3.js, from compiling and deploying Solidity contracts to interacting with deployed smart contracts. + +# Web3.js + +!!! 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. + +## Introduction + +Interacting with blockchains typically requires an interface between your application and the network. [Web3.js](https://web3js.readthedocs.io/){target=\_blank} offers this interface through a comprehensive collection of libraries, facilitating seamless interaction with the nodes using HTTP or WebSocket protocols. This guide illustrates how to utilize Web3.js specifically for interactions with Polkadot Hub. + +This guide is intended for developers who are familiar with JavaScript and want to interact with the Polkadot Hub using Web3.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="Web3.js Polkadot Hub" +web3js-project +├── contracts +│ ├── Storage.sol +├── scripts +│ ├── connectToProvider.js +│ ├── fetchLastBlock.js +│ ├── compile.js +│ ├── deploy.js +│ ├── updateStorage.js +├── abis +│ ├── Storage.json +├── artifacts +│ ├── Storage.bin +├── contract-address.json +├── node_modules/ +├── package.json +├── package-lock.json +└── README.md +``` + +## Set Up the Project + +To start working with Web3.js, create a new folder and initialize your project by running the following commands in your terminal: + +```bash +mkdir web3js-project +cd web3js-project +npm init -y +``` + +## Install Dependencies + +Next, run the following command to install the Web3.js library: + +```bash +npm install web3 +``` + +Add the Solidity compiler so you can generate standard EVM bytecode: + +```bash +npm install --save-dev solc +``` + +!!! tip + The sample scripts use ECMAScript modules. Add `"type": "module"` to your `package.json` (or rename the files to `.mjs`) so that `node` can run the `import` statements. + +## Set Up the Web3 Provider + +The provider configuration is the foundation of any Web3.js application. It serves as a bridge between your application and the blockchain, allowing you to query blockchain data and interact with smart contracts. + +To interact with Polkadot Hub, you must set up a Web3.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 { Web3 } = require('web3'); + +const createProvider = (rpcUrl) => { + const web3 = new Web3(rpcUrl); + return web3; +}; + +const PROVIDER_RPC = { + rpc: 'INSERT_RPC_URL', + chainId: 'INSERT_CHAIN_ID', + name: 'INSERT_CHAIN_NAME', +}; + +createProvider(PROVIDER_RPC.rpc); + +``` + +!!! 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 scripts/connectToProvider.js +``` + +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 { Web3 } = require('web3'); + + const createProvider = (rpcUrl) => { + const web3 = new Web3(rpcUrl); + return web3; + }; + + const PROVIDER_RPC = { + rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', + chainId: 420420422, + name: 'polkadot-hub-testnet', + }; + + const main = async () => { + try { + const web3 = createProvider(PROVIDER_RPC.rpc); + const latestBlock = await web3.eth.getBlockNumber(); + console.log('Last block: ' + latestBlock); + } catch (error) { + console.error('Error connecting to Polkadot Hub TestNet: ' + error.message); + } + }; + + main(); + + ``` + +## Compile Contracts + +Polkadot Hub exposes an Ethereum JSON-RPC endpoint, so you can compile Solidity contracts to familiar EVM bytecode with the upstream [`solc`](https://www.npmjs.com/package/solc){target=\_blank} compiler. The resulting artifacts work with any EVM-compatible toolchain and can be deployed through Web3.js. + +### 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 +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 solc = require('solc'); +const { readFileSync, writeFileSync, mkdirSync, existsSync } = require('fs'); +const { basename, join } = require('path'); + +const ensureDir = (dirPath) => { + if (!existsSync(dirPath)) { + mkdirSync(dirPath, { recursive: true }); + } +}; + +const compileContract = (solidityFilePath, abiDir, artifactsDir) => { + try { + // Read the Solidity file + const source = readFileSync(solidityFilePath, 'utf8'); + const fileName = basename(solidityFilePath); + + // Construct the input object for the Solidity compiler + const input = { + language: 'Solidity', + sources: { + [fileName]: { + content: source, + }, + }, + settings: { + outputSelection: { + '*': { + '*': ['abi', 'evm.bytecode'], + }, + }, + }, + }; + + console.log(`Compiling contract: ${fileName}...`); + + // Compile the contract + const output = JSON.parse(solc.compile(JSON.stringify(input))); + + // Check for errors + if (output.errors) { + const errors = output.errors.filter(error => error.severity === 'error'); + if (errors.length > 0) { + console.error('Compilation errors:'); + errors.forEach(err => console.error(err.formattedMessage)); + return; + } + // Show warnings + const warnings = output.errors.filter(error => error.severity === 'warning'); + warnings.forEach(warn => console.warn(warn.formattedMessage)); + } + + // Ensure output directories exist + ensureDir(abiDir); + ensureDir(artifactsDir); + + // Process compiled contracts + for (const [sourceFile, contracts] of Object.entries(output.contracts)) { + for (const [contractName, contract] of Object.entries(contracts)) { + console.log(`Compiled contract: ${contractName}`); + + // Write the ABI + const abiPath = join(abiDir, `${contractName}.json`); + writeFileSync(abiPath, JSON.stringify(contract.abi, null, 2)); + console.log(`ABI saved to ${abiPath}`); + + // Write the bytecode + const bytecodePath = join(artifactsDir, `${contractName}.bin`); + writeFileSync(bytecodePath, contract.evm.bytecode.object); + console.log(`Bytecode saved to ${bytecodePath}`); + } + } + } catch (error) { + console.error('Error compiling contracts:', error); + } +}; + +const solidityFilePath = join(__dirname, '../contracts/Storage.sol'); +const abiDir = join(__dirname, '../abis'); +const artifactsDir = join(__dirname, '../artifacts'); + +compileContract(solidityFilePath, abiDir, artifactsDir); +``` + +!!! 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 scripts/compile.js +``` + +After executing the script, the Solidity contract is compiled into standard EVM bytecode. The ABI and bytecode are saved into files with `.json` and `.bin` 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" + const { writeFileSync, existsSync, readFileSync } = require('fs'); + const { join } = require('path'); + const { Web3 } = require('web3'); + + const scriptsDir = __dirname; + const abisDir = join(__dirname, '../abis'); + const artifactsDir = join(__dirname, '../artifacts'); + ``` + +2. Create a provider to connect to Polkadot Hub: + + ```js title="scripts/deploy.js" + const createProvider = (rpcUrl, chainId, chainName) => { + const web3 = new Web3(rpcUrl); + return web3; + }; + ``` + +3. Set up functions to read contract artifacts: + + ```js title="scripts/deploy.js" + const getAbi = (contractName) => { + try { + const abiPath = join(abisDir, `${contractName}.json`); + return JSON.parse(readFileSync(abiPath, 'utf8')); + } catch (error) { + console.error( + `Could not find ABI for contract ${contractName}:`, + error.message, + ); + throw error; + } + }; + + const getByteCode = (contractName) => { + try { + const bytecodePath = join(artifactsDir, `${contractName}.bin`); + const bytecode = readFileSync(bytecodePath, 'utf8').trim(); + return bytecode.startsWith('0x') ? bytecode : `0x${bytecode}`; + } 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, privateKey, providerConfig) => { + console.log(`Deploying ${contractName}...`); + try { + const web3 = createProvider( + providerConfig.rpc, + providerConfig.chainId, + providerConfig.name, + ); + + const formattedPrivateKey = privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`; + const account = web3.eth.accounts.privateKeyToAccount(formattedPrivateKey); + web3.eth.accounts.wallet.add(account); + web3.eth.defaultAccount = account.address; + + const abi = getAbi(contractName); + const bytecode = getByteCode(contractName); + const contract = new web3.eth.Contract(abi); + const deployTx = contract.deploy({ + data: bytecode, + }); + + const gas = await deployTx.estimateGas(); + const gasPrice = await web3.eth.getGasPrice(); + + console.log(`Estimated gas: ${gas}`); + console.log(`Gas price: ${web3.utils.fromWei(gasPrice, 'gwei')} gwei`); + + const deployedContract = await deployTx.send({ + from: account.address, + gas: gas, + gasPrice: gasPrice, + }); + + const address = deployedContract.options.address; + console.log(`Contract ${contractName} deployed at: ${address}`); + + const addressesFile = join(scriptsDir, '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', // TODO: replace to `https://services.polkadothub-rpc.com/testnet` when ready + chainId: 420420422, + name: 'polkadot-hub-testnet', + }; + + const privateKey = 'INSERT_PRIVATE_KEY'; + + deployContract('Storage', privateKey, providerConfig); + ``` + + !!! note + + A private key is a hexadecimal string that is used to sign and pay for the deployment transaction. **Always keep your private key secure and never share it publicly**. + + Ensure to replace the `INSERT_PRIVATE_KEY` placeholder with your actual private key. + +??? code "View complete script" + + ```js title="scripts/deploy.js" + const { writeFileSync, existsSync, readFileSync } = require('fs'); + const { join } = require('path'); + const { Web3 } = require('web3'); + + const scriptsDir = __dirname; + const abisDir = join(__dirname, '../abis'); + const artifactsDir = join(__dirname, '../artifacts'); + + const createProvider = (rpcUrl, chainId, chainName) => { + const web3 = new Web3(rpcUrl); + return web3; + }; + + const getAbi = (contractName) => { + try { + const abiPath = join(abisDir, `${contractName}.json`); + return JSON.parse(readFileSync(abiPath, 'utf8')); + } catch (error) { + console.error( + `Could not find ABI for contract ${contractName}:`, + error.message, + ); + throw error; + } + }; + + const getByteCode = (contractName) => { + try { + const bytecodePath = join(artifactsDir, `${contractName}.bin`); + const bytecode = readFileSync(bytecodePath, 'utf8').trim(); + return bytecode.startsWith('0x') ? bytecode : `0x${bytecode}`; + } catch (error) { + console.error( + `Could not find bytecode for contract ${contractName}:`, + error.message, + ); + throw error; + } + }; + + const deployContract = async (contractName, privateKey, providerConfig) => { + console.log(`Deploying ${contractName}...`); + try { + const web3 = createProvider( + providerConfig.rpc, + providerConfig.chainId, + providerConfig.name, + ); + + const formattedPrivateKey = privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`; + const account = web3.eth.accounts.privateKeyToAccount(formattedPrivateKey); + web3.eth.accounts.wallet.add(account); + web3.eth.defaultAccount = account.address; + + const abi = getAbi(contractName); + const bytecode = getByteCode(contractName); + const contract = new web3.eth.Contract(abi); + const deployTx = contract.deploy({ + data: bytecode, + }); + + const gas = await deployTx.estimateGas(); + const gasPrice = await web3.eth.getGasPrice(); + + console.log(`Estimated gas: ${gas}`); + console.log(`Gas price: ${web3.utils.fromWei(gasPrice, 'gwei')} gwei`); + + const deployedContract = await deployTx.send({ + from: account.address, + gas: gas, + gasPrice: gasPrice, + }); + + const address = deployedContract.options.address; + console.log(`Contract ${contractName} deployed at: ${address}`); + + const addressesFile = join(scriptsDir, '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', // TODO: replace to `https://services.polkadothub-rpc.com/testnet` when ready + chainId: 420420422, + name: 'polkadot-hub-testnet', + }; + + const privateKey = 'INSERT_PRIVATE_KEY'; + + deployContract('Storage', privateKey, providerConfig); + + + ``` + +To run the script, execute the following command: + +```bash +node scripts/deploy.js +``` + +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 `updateStorage.js` in the root of your project and add the following code: + +```js title="scripts/updateStorage.js" +const { readFileSync } = require('fs'); +const { join } = require('path'); +const { Web3 } = require('web3'); + +const abisDir = join(__dirname, '../abis'); + +const getAbi = (contractName) => { + try { + const abiPath = join(abisDir, `${contractName}.json`); + return JSON.parse(readFileSync(abiPath, 'utf8')); + } catch (error) { + console.error( + `Could not find ABI for contract ${contractName}:`, + error.message, + ); + throw error; + } +}; + +const updateStorage = async (config) => { + try { + const web3 = new Web3(config.rpcUrl); + const formattedPrivateKey = config.privateKey.startsWith('0x') ? config.privateKey : `0x${config.privateKey}`; + const account = web3.eth.accounts.privateKeyToAccount(formattedPrivateKey); + web3.eth.accounts.wallet.add(account); + + const abi = getAbi('Storage'); + const contract = new web3.eth.Contract(abi, config.contractAddress); + + const initialValue = await contract.methods.storedNumber().call(); + console.log('Current stored value:', initialValue); + + const updateTransaction = contract.methods.setNumber(1); + const gasEstimate = await updateTransaction.estimateGas({ + from: account.address, + }); + const gasPrice = await web3.eth.getGasPrice(); + + const receipt = await updateTransaction.send({ + from: account.address, + gas: gasEstimate, + gasPrice: gasPrice, + }); + + console.log(`Transaction hash: ${receipt.transactionHash}`); + + const newValue = await contract.methods.storedNumber().call(); + console.log('New stored value:', newValue); + + return receipt; + } catch (error) { + console.error('Update failed:', error); + throw error; + } +}; + +const config = { + rpcUrl: 'https://testnet-passet-hub-eth-rpc.polkadot.io', + privateKey: 'INSERT_PRIVATE_KEY', + contractAddress: 'INSERT_CONTRACT_ADDRESS', +}; + +updateStorage(config) + .then((receipt) => console.log('Update successful')) + .catch((error) => console.error('Update error')); +``` + +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. The script prints the balance for `ADDRESS_TO_CHECK` before it writes and doubles the stored value, so pick any account you want to monitor. + +To interact with the contract, run: + +```bash +node scripts/updateStorage.js +``` + +## Where to Go Next + +Now that you have the foundational knowledge to use Web3.js with Polkadot Hub, you can: + +- **Dive into Web3.js utilities**: Discover additional Web3.js features, such as wallet management, signing messages, subscribing to events, etc. + +- **Implement batch transactions**: Use Web3.js to execute batch transactions for efficient multi-step contract interactions. + +- **Build scalable applications**: Combine Web3.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: Deploying Uniswap V2 on Polkadot @@ -12671,597 +13286,166 @@ Wallet types fall into two categories based on their connection to the internet: ## Cold Wallets -
- -- __Ledger__ - - --- - - A hardware wallet that securely stores cryptocurrency private keys offline, protecting them from online threats. Using a secure chip and the Ledger Live app allows safe transactions and asset management while keeping keys secure. - - [:octicons-arrow-right-24: Reference](https://www.ledger.com/){target=\_blank} - -- __Polkadot Vault__ - - --- - - This cold storage solution lets you use a phone in airplane mode as an air-gapped wallet, turning any spare phone, tablet, or iOS/Android device into a hardware wallet. - - [:octicons-arrow-right-24: Reference](https://vault.novasama.io/){target=\_blank} - -
- -## Wallet Tools - -
- -- __LunoKit__ - - --- - - A React library for integrating Polkadot wallet connections into dApps. It offers a unified API for major wallets like Polkadot.js, SubWallet, Talisman, Nova Wallet, PolkaGate, WalletConnect, Enkrypt, Fearless, and Mimir. Includes customizable UI components, React hooks, full TypeScript and multi-chain support, and flexible integration with APIs such as Dedot, PAPI, or Polkadot.js. - - [:octicons-arrow-right-24: Reference](https://www.lunolab.xyz/){target=\_blank} - - -
- - ---- - -Page Title: Wallets for Polkadot Hub - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-wallets.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/integrations/wallets/ -- Summary: Comprehensive guide to connecting and managing wallets for Polkadot Hub, covering step-by-step instructions for interacting with the ecosystem. - -# 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. - -## Connect Your Wallet - -### MetaMask - -[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. - -To 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. - -For example, to connect to the Polkadot Hub TestNet via MetaMask, you need to follow these steps: - -1. Open the MetaMask extension and click on the network icon to switch to the Polkadot Hub TestNet. - - ![](/images/smart-contracts/integrations/wallets/wallets-1.webp){: .browser-extension} - -2. Click on the **Add a custom network** button. - - ![](/images/smart-contracts/integrations/wallets/wallets-2.webp){: .browser-extension} - -3. 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). - - ![](/images/smart-contracts/integrations/wallets/wallets-3.webp){: .browser-extension} - -4. Click on **Polkadot Hub TestNet** to switch the network. - - ![](/images/smart-contracts/integrations/wallets/wallets-4.webp){: .browser-extension} - -The steps in the preceding section can be used to connect to any chain by modifying the network specification and endpoint parameters. - -### SubWallet - -[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. - -SubWallet 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. - -You 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). - -??? code "Polkadot Hub TestNet" - 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. - The ETH RPC endpoint will let you send transactions that follow an ETH format, while the Substrate endpoint will follow a Substrate transaction format. - Note the PAS token, which is the native token of the Polkadot Hub TestNet. - - ![](/images/smart-contracts/integrations/wallets/subwallet-PAS.webp){: .browser-extension} - -To connect to Polkadot Hub TestNet using SubWallet, follow these steps: - -1. 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. - -2. After setting up your wallet, click the List icon at the top left corner of the extension window to open **Settings**. - - ![](/images/smart-contracts/integrations/wallets/subwallet-01.webp){: .browser-extension} - -3. Scroll down and select **Manage networks**. - - ![](/images/smart-contracts/integrations/wallets/subwallet-02.webp){: .browser-extension} - -4. 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. - - ![](/images/smart-contracts/integrations/wallets/subwallet-03.webp){: .browser-extension} - - You are now ready to use SubWallet to interact with [Polkadot Hub TestNet](/smart-contracts/connect/#networks-details){target=\_blank} seamlessly! - -![](/images/smart-contracts/integrations/wallets/subwallet-04.webp){: .browser-extension} - -### Talisman - -[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. - -To use Talisman with Polkadot Hub TestNet: - -1. Install the [Talisman extension](https://talisman.xyz/download){target=\_blank} and set up your wallet by following the on-screen instructions. - -2. Once installed, click on the Talisman icon in your browser extensions and click on the **Settings** button. - - ![](/images/smart-contracts/integrations/wallets/wallets-5.webp){: .browser-extension} - -3. Click the button **All settings**. - - ![](/images/smart-contracts/integrations/wallets/wallets-6.webp){: .browser-extension} - -4. Go to the **Networks & Tokens** section. - - ![](/images/smart-contracts/integrations/wallets/wallets-7.webp) - -5. Click the **Manage networks** button. - - ![](/images/smart-contracts/integrations/wallets/wallets-8.webp) - -6. Click the **+ Add network** button. - - ![](/images/smart-contracts/integrations/wallets/wallets-9.webp) - -7. Fill in the form with the required parameters and click the **Add network** button. - - ![](/images/smart-contracts/integrations/wallets/wallets-10.webp) - -8. After that, you can switch to the Polkadot Hub TestNet by clicking on the network icon and selecting **Polkadot Hub TestNet**. - - ![](/images/smart-contracts/integrations/wallets/wallets-11.webp) - -After 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. - - -## Conclusion - -Choosing 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. - -!!!info - Remember to always verify network parameters when connecting to ensure a secure and reliable connection to the Polkadot ecosystem. - - ---- - -Page Title: Web3.js - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-web3-js.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/libraries/web3-js/ -- Summary: Learn how to interact with Polkadot Hub using Web3.js, deploying Solidity contracts, and interacting with deployed smart contracts. - -# Web3.js - -!!! 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. - -## Introduction - -Interacting with blockchains typically requires an interface between your application and the network. [Web3.js](https://web3js.readthedocs.io/){target=\_blank} offers this interface through a comprehensive collection of libraries, facilitating seamless interaction with the nodes using HTTP or WebSocket protocols. This guide illustrates how to utilize Web3.js specifically for interactions with Polkadot Hub. - -This guide is intended for developers who are familiar with JavaScript and want to interact with the Polkadot Hub using Web3.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="Web3.js Polkadot Hub" -web3js-project -├── contracts -│ ├── Storage.sol -├── scripts -│ ├── connectToProvider.js -│ ├── fetchLastBlock.js -│ ├── compile.js -│ ├── deploy.js -│ ├── updateStorage.js -├── abis -│ ├── Storage.json -├── artifacts -│ ├── Storage.polkavm -├── node_modules/ -├── package.json -├── package-lock.json -└── README.md -``` - -## Set Up the Project - -To start working with Web3.js, begin by initializing your project: - -```bash -npm init -y -``` - -## Install Dependencies - -Next, install the Web3.js library: - -```bash -npm install web3 -``` - -This guide uses `web3` version `4.16.0`. - -## Set Up the Web3 Provider - -The provider configuration is the foundation of any Web3.js application. The following example establishes a connection to Polkadot Hub. To use the example script, replace `INSERT_RPC_URL`, `INSERT_CHAIN_ID`, and `INSERT_CHAIN_NAME` with the appropriate values. The provider connection script should look something like this: - -```javascript title="scripts/connectToProvider.js" -const { Web3 } = require('web3'); - -const createProvider = (rpcUrl) => { - const web3 = new Web3(rpcUrl); - return web3; -}; - -const PROVIDER_RPC = { - rpc: 'INSERT_RPC_URL', - chainId: 'INSERT_CHAIN_ID', - name: 'INSERT_CHAIN_NAME', -}; - -createProvider(PROVIDER_RPC.rpc); - -``` - -For example, for the Polkadot Hub TestNet, use these specific connection parameters: - -```js -const PROVIDER_RPC = { - rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', - chainId: 420420422, - name: 'polkadot-hub-testnet' -}; -``` - -With the Web3 provider set up, you can start querying the blockchain. +
-For instance, to fetch the latest block number of the chain, you can use the following code snippet: +- __Ledger__ -???+ code "View complete script" + --- - ```javascript title="scripts/fetchLastBlock.js" - const { Web3 } = require('web3'); + A hardware wallet that securely stores cryptocurrency private keys offline, protecting them from online threats. Using a secure chip and the Ledger Live app allows safe transactions and asset management while keeping keys secure. - const createProvider = (rpcUrl) => { - const web3 = new Web3(rpcUrl); - return web3; - }; + [:octicons-arrow-right-24: Reference](https://www.ledger.com/){target=\_blank} - const PROVIDER_RPC = { - rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', - chainId: 420420422, - name: 'polkadot-hub-testnet', - }; +- __Polkadot Vault__ - const main = async () => { - try { - const web3 = createProvider(PROVIDER_RPC.rpc); - const latestBlock = await web3.eth.getBlockNumber(); - console.log('Last block: ' + latestBlock); - } catch (error) { - console.error('Error connecting to Polkadot Hub TestNet: ' + error.message); - } - }; + --- - main(); + This cold storage solution lets you use a phone in airplane mode as an air-gapped wallet, turning any spare phone, tablet, or iOS/Android device into a hardware wallet. - ``` + [:octicons-arrow-right-24: Reference](https://vault.novasama.io/){target=\_blank} -## 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. +## Wallet Tools - 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. +
-Polkadot Hub requires contracts to be compiled to [PolkaVM](/smart-contracts/for-eth-devs/dual-vm-stack/){target=\_blank} bytecode. This is achieved using the [`revive`](https://github.com/paritytech/revive/tree/v0.2.0/js/resolc){target=\_blank} compiler. Install the [`@parity/resolc`](https://github.com/paritytech/revive){target=\_blank} library as a development dependency: +- __LunoKit__ -```bash -npm install --save-dev @parity/resolc -``` + --- -This guide uses `@parity/resolc` version `0.2.0`. + A React library for integrating Polkadot wallet connections into dApps. It offers a unified API for major wallets like Polkadot.js, SubWallet, Talisman, Nova Wallet, PolkaGate, WalletConnect, Enkrypt, Fearless, and Mimir. Includes customizable UI components, React hooks, full TypeScript and multi-chain support, and flexible integration with APIs such as Dedot, PAPI, or Polkadot.js. -Here's a simple storage contract that you can use to follow the process: + [:octicons-arrow-right-24: Reference](https://www.lunolab.xyz/){target=\_blank} -```solidity title="contracts/Storage.sol" -//SPDX-License-Identifier: MIT -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; - } -} -``` -With that, you can now create a `compile.js` snippet that transforms your solidity code into PolkaVM bytecode: +--- -```javascript title="scripts/compile.js" -const { compile } = require('@parity/resolc'); -const { readFileSync, writeFileSync } = require('fs'); -const { basename, join } = require('path'); +Page Title: Wallets for Polkadot Hub -const compileContract = async (solidityFilePath, outputDir) => { - try { - // Read the Solidity file - const source = readFileSync(solidityFilePath, 'utf8'); +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-wallets.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/integrations/wallets/ +- Summary: Comprehensive guide to connecting and managing wallets for Polkadot Hub, covering step-by-step instructions for interacting with the ecosystem. - // Construct the input object for the compiler - const input = { - [basename(solidityFilePath)]: { content: source }, - }; +# Wallets for Polkadot Hub - console.log(`Compiling contract: ${basename(solidityFilePath)}...`); +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. +## Introduction - // Compile the contract - const out = await compile(input); +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. - for (const contracts of Object.values(out.contracts)) { - for (const [name, contract] of Object.entries(contracts)) { - console.log(`Compiled contract: ${name}`); +## Connect Your Wallet - // Write the ABI - const abiPath = join(outputDir, `${name}.json`); - writeFileSync(abiPath, JSON.stringify(contract.abi, null, 2)); - console.log(`ABI saved to ${abiPath}`); +### MetaMask - // 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); - } -}; +[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. -const solidityFilePath = './Storage.sol'; -const outputDir = '.'; +To 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. -compileContract(solidityFilePath, outputDir); +For example, to connect to the Polkadot Hub TestNet via MetaMask, you need to follow these steps: -``` +1. Open the MetaMask extension and click on the network icon to switch to the Polkadot Hub TestNet. -To compile your contract, simply run the following command: + ![](/images/smart-contracts/integrations/wallets/wallets-1.webp){: .browser-extension} -```bash -node compile -``` +2. Click on the **Add a custom network** button. -After compilation, you'll have two key files: an ABI (`.json`) file, which provides a JSON interface describing the contract's functions and how to interact with it, and a bytecode (`.polkavm`) file, which contains the low-level machine code executable on PolkaVM that represents the compiled smart contract ready for blockchain deployment. + ![](/images/smart-contracts/integrations/wallets/wallets-2.webp){: .browser-extension} -## Contract Deployment +3. 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). -To deploy your compiled contract to Polkadot Hub using Web3.js, you'll need an account with a private key to sign the deployment transaction. The deployment process is exactly the same as for any Ethereum-compatible chain, involving creating a contract instance, estimating gas, and sending a deployment transaction. Here's how to deploy the contract, ensure replacing the `INSERT_RPC_URL`, `INSERT_PRIVATE_KEY`, and `INSERT_CONTRACT_NAME` with the appropriate values: + ![](/images/smart-contracts/integrations/wallets/wallets-3.webp){: .browser-extension} -```javascript title="scripts/deploy.js" -import { readFileSync } from 'fs'; -import { Web3 } from 'web3'; +4. Click on **Polkadot Hub TestNet** to switch the network. -const getAbi = (contractName) => { - try { - return JSON.parse(readFileSync(`${contractName}.json`), 'utf8'); - } catch (error) { - console.error( - `❌ Could not find ABI for contract ${contractName}:`, - error.message - ); - throw error; - } -}; + ![](/images/smart-contracts/integrations/wallets/wallets-4.webp){: .browser-extension} -const getByteCode = (contractName) => { - try { - return `0x${readFileSync(`${contractName}.polkavm`).toString('hex')}`; - } catch (error) { - console.error( - `❌ Could not find bytecode for contract ${contractName}:`, - error.message - ); - throw error; - } -}; +The steps in the preceding section can be used to connect to any chain by modifying the network specification and endpoint parameters. -export const deploy = async (config) => { - try { - // Initialize Web3 with RPC URL - const web3 = new Web3(config.rpcUrl); +### SubWallet - // Prepare account - const account = web3.eth.accounts.privateKeyToAccount(config.privateKey); - web3.eth.accounts.wallet.add(account); +[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. - // Load abi - const abi = getAbi('Storage'); +SubWallet 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. - // Create contract instance - const contract = new web3.eth.Contract(abi); +You 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). - // Prepare deployment - const deployTransaction = contract.deploy({ - data: getByteCode('Storage'), - arguments: [], // Add constructor arguments if needed - }); +??? code "Polkadot Hub TestNet" + 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. + The ETH RPC endpoint will let you send transactions that follow an ETH format, while the Substrate endpoint will follow a Substrate transaction format. + Note the PAS token, which is the native token of the Polkadot Hub TestNet. - // Estimate gas - const gasEstimate = await deployTransaction.estimateGas({ - from: account.address, - }); + ![](/images/smart-contracts/integrations/wallets/subwallet-PAS.webp){: .browser-extension} - // Get current gas price - const gasPrice = await web3.eth.getGasPrice(); +To connect to Polkadot Hub TestNet using SubWallet, follow these steps: - // Send deployment transaction - const deployedContract = await deployTransaction.send({ - from: account.address, - gas: gasEstimate, - gasPrice: gasPrice, - }); +1. 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. - // Log and return contract details - console.log(`Contract deployed at: ${deployedContract.options.address}`); - return deployedContract; - } catch (error) { - console.error('Deployment failed:', error); - throw error; - } -}; +2. After setting up your wallet, click the List icon at the top left corner of the extension window to open **Settings**. -// Example usage -const deploymentConfig = { - rpcUrl: 'INSERT_RPC_URL', - privateKey: 'INSERT_PRIVATE_KEY', - contractName: 'INSERT_CONTRACT_NAME', -}; + ![](/images/smart-contracts/integrations/wallets/subwallet-01.webp){: .browser-extension} -deploy(deploymentConfig) - .then((contract) => console.log('Deployment successful')) - .catch((error) => console.error('Deployment error')); +3. Scroll down and select **Manage networks**. -``` + ![](/images/smart-contracts/integrations/wallets/subwallet-02.webp){: .browser-extension} -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}. +4. 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. -To deploy your contract, run the following command: + ![](/images/smart-contracts/integrations/wallets/subwallet-03.webp){: .browser-extension} -```bash -node deploy -``` + You are now ready to use SubWallet to interact with [Polkadot Hub TestNet](/smart-contracts/connect/#networks-details){target=\_blank} seamlessly! -## Interact with the Contract +![](/images/smart-contracts/integrations/wallets/subwallet-04.webp){: .browser-extension} -Once deployed, you can interact with your contract using Web3.js methods. Here's how to set a number and read it back, ensure replacing `INSERT_RPC_URL`, `INSERT_PRIVATE_KEY`, and `INSERT_CONTRACT_ADDRESS` with the appropriate values: +### Talisman -```javascript title="scripts/updateStorage.js" -import { readFileSync } from 'fs'; -import { Web3 } from 'web3'; +[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. -const getAbi = (contractName) => { - try { - return JSON.parse(readFileSync(`${contractName}.json`), 'utf8'); - } catch (error) { - console.error( - `❌ Could not find ABI for contract ${contractName}:`, - error.message - ); - throw error; - } -}; +To use Talisman with Polkadot Hub TestNet: -const updateStorage = async (config) => { - try { - // Initialize Web3 with RPC URL - const web3 = new Web3(config.rpcUrl); +1. Install the [Talisman extension](https://talisman.xyz/download){target=\_blank} and set up your wallet by following the on-screen instructions. - // Prepare account - const account = web3.eth.accounts.privateKeyToAccount(config.privateKey); - web3.eth.accounts.wallet.add(account); +2. Once installed, click on the Talisman icon in your browser extensions and click on the **Settings** button. - // Load abi - const abi = getAbi('Storage'); + ![](/images/smart-contracts/integrations/wallets/wallets-5.webp){: .browser-extension} - // Create contract instance - const contract = new web3.eth.Contract(abi, config.contractAddress); +3. Click the button **All settings**. - // Get initial value - const initialValue = await contract.methods.storedNumber().call(); - console.log('Current stored value:', initialValue); + ![](/images/smart-contracts/integrations/wallets/wallets-6.webp){: .browser-extension} - // Prepare transaction - const updateTransaction = contract.methods.setNumber(1); +4. Go to the **Networks & Tokens** section. - // Estimate gas - const gasEstimate = await updateTransaction.estimateGas({ - from: account.address, - }); + ![](/images/smart-contracts/integrations/wallets/wallets-7.webp) - // Get current gas price - const gasPrice = await web3.eth.getGasPrice(); +5. Click the **Manage networks** button. - // Send update transaction - const receipt = await updateTransaction.send({ - from: account.address, - gas: gasEstimate, - gasPrice: gasPrice, - }); + ![](/images/smart-contracts/integrations/wallets/wallets-8.webp) - // Log transaction details - console.log(`Transaction hash: ${receipt.transactionHash}`); +6. Click the **+ Add network** button. - // Get updated value - const newValue = await contract.methods.storedNumber().call(); - console.log('New stored value:', newValue); + ![](/images/smart-contracts/integrations/wallets/wallets-9.webp) - return receipt; - } catch (error) { - console.error('Update failed:', error); - throw error; - } -}; +7. Fill in the form with the required parameters and click the **Add network** button. -// Example usage -const config = { - rpcUrl: 'INSERT_RPC_URL', - privateKey: 'INSERT_PRIVATE_KEY', - contractAddress: 'INSERT_CONTRACT_ADDRESS', -}; + ![](/images/smart-contracts/integrations/wallets/wallets-10.webp) -updateStorage(config) - .then((receipt) => console.log('Update successful')) - .catch((error) => console.error('Update error')); +8. After that, you can switch to the Polkadot Hub TestNet by clicking on the network icon and selecting **Polkadot Hub TestNet**. -``` + ![](/images/smart-contracts/integrations/wallets/wallets-11.webp) -To execute the logic above, run: +After 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. -```bash -node updateStorage -``` -## Where to Go Next +## Conclusion -Now that you’ve learned how to use Web3.js with Polkadot Hub, explore more advanced topics: +Choosing 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. -- **Utilize Web3.js utilities**: Learn about additional [Web3.js](https://docs.web3js.org/){target=\_blank} features such as signing transactions, managing wallets, and subscribing to events. -- **Build full-stack dApps**: [integrate Web3.js](https://docs.web3js.org/guides/dapps/intermediate-dapp){target=\_blank} with different libraries and frameworks to build decentralized web applications. +!!!info + Remember to always verify network parameters when connecting to ensure a secure and reliable connection to the Polkadot ecosystem. --- diff --git a/.ai/pages/smart-contracts-libraries-web3-js.md b/.ai/pages/smart-contracts-libraries-web3-js.md index 095b6ea5c..ce4a2e8b4 100644 --- a/.ai/pages/smart-contracts-libraries-web3-js.md +++ b/.ai/pages/smart-contracts-libraries-web3-js.md @@ -1,14 +1,12 @@ --- -title: Web3.js -description: Learn how to interact with Polkadot Hub using Web3.js, deploying Solidity contracts, and interacting with deployed smart contracts. +title: Deploy Contracts to Polkadot Hub with Web3.js +description: Learn how to interact with Polkadot Hub using Web3.js, from compiling and deploying Solidity contracts to interacting with deployed smart contracts. categories: Smart Contracts, Tooling url: https://docs.polkadot.com/smart-contracts/libraries/web3-js/ --- # Web3.js -!!! 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. @@ -43,7 +41,8 @@ web3js-project ├── abis │ ├── Storage.json ├── artifacts -│ ├── Storage.polkavm +│ ├── Storage.bin +├── contract-address.json ├── node_modules/ ├── package.json ├── package-lock.json @@ -52,27 +51,38 @@ web3js-project ## Set Up the Project -To start working with Web3.js, begin by initializing your project: +To start working with Web3.js, create a new folder and initialize your project by running the following commands in your terminal: ```bash +mkdir web3js-project +cd web3js-project npm init -y ``` ## Install Dependencies -Next, install the Web3.js library: +Next, run the following command to install the Web3.js library: ```bash npm install web3 ``` -This guide uses `web3` version `4.16.0`. +Add the Solidity compiler so you can generate standard EVM bytecode: + +```bash +npm install --save-dev solc +``` + +!!! tip + The sample scripts use ECMAScript modules. Add `"type": "module"` to your `package.json` (or rename the files to `.mjs`) so that `node` can run the `import` statements. ## Set Up the Web3 Provider -The provider configuration is the foundation of any Web3.js application. The following example establishes a connection to Polkadot Hub. To use the example script, replace `INSERT_RPC_URL`, `INSERT_CHAIN_ID`, and `INSERT_CHAIN_NAME` with the appropriate values. The provider connection script should look something like this: +The provider configuration is the foundation of any Web3.js application. It serves as a bridge between your application and the blockchain, allowing you to query blockchain data and interact with smart contracts. + +To interact with Polkadot Hub, you must set up a Web3.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: -```javascript title="scripts/connectToProvider.js" +```js title="scripts/connectToProvider.js" const { Web3 } = require('web3'); const createProvider = (rpcUrl) => { @@ -90,23 +100,28 @@ createProvider(PROVIDER_RPC.rpc); ``` -For example, for the Polkadot Hub TestNet, use these specific connection parameters: +!!! 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' -}; -``` + ```js + const PROVIDER_RPC = { + rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', + chainId: 420420422, + name: 'polkadot-hub-testnet' + }; + ``` -With the Web3 provider set up, you can start querying the blockchain. +To connect to the provider, execute: -For instance, to fetch the latest block number of the chain, you can use the following code snippet: +```bash +node scripts/connectToProvider.js +``` -???+ code "View complete script" +With the provider set up, you can start querying the blockchain. For instance, to fetch the latest block number: - ```javascript title="scripts/fetchLastBlock.js" +??? code "Fetch Last Block code" + + ```js title="scripts/fetchLastBlock.js" const { Web3 } = require('web3'); const createProvider = (rpcUrl) => { @@ -136,20 +151,11 @@ For instance, to fetch the latest block number of the chain, you can use the fol ## 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. +Polkadot Hub exposes an Ethereum JSON-RPC endpoint, so you can compile Solidity contracts to familiar EVM bytecode with the upstream [`solc`](https://www.npmjs.com/package/solc){target=\_blank} compiler. The resulting artifacts work with any EVM-compatible toolchain and can be deployed through Web3.js. -Polkadot Hub requires contracts to be compiled to [PolkaVM](/smart-contracts/for-eth-devs/dual-vm-stack/){target=\_blank} bytecode. This is achieved using the [`revive`](https://github.com/paritytech/revive/tree/v0.2.0/js/resolc){target=\_blank} compiler. Install the [`@parity/resolc`](https://github.com/paritytech/revive){target=\_blank} library as a development dependency: +### Sample Storage Smart Contract -```bash -npm install --save-dev @parity/resolc -``` - -This guide uses `@parity/resolc` version `0.2.0`. - -Here's a simple storage contract that you can use to follow the process: +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 @@ -172,43 +178,79 @@ contract Storage { } ``` -With that, you can now create a `compile.js` snippet that transforms your solidity code into PolkaVM bytecode: +### Compile the Smart Contract + +To compile this contract, use the following script: -```javascript title="scripts/compile.js" -const { compile } = require('@parity/resolc'); -const { readFileSync, writeFileSync } = require('fs'); +```js title="scripts/compile.js" +const solc = require('solc'); +const { readFileSync, writeFileSync, mkdirSync, existsSync } = require('fs'); const { basename, join } = require('path'); -const compileContract = async (solidityFilePath, outputDir) => { +const ensureDir = (dirPath) => { + if (!existsSync(dirPath)) { + mkdirSync(dirPath, { recursive: true }); + } +}; + +const compileContract = (solidityFilePath, abiDir, artifactsDir) => { try { // Read the Solidity file const source = readFileSync(solidityFilePath, 'utf8'); - - // Construct the input object for the compiler + const fileName = basename(solidityFilePath); + + // Construct the input object for the Solidity compiler const input = { - [basename(solidityFilePath)]: { content: source }, + language: 'Solidity', + sources: { + [fileName]: { + content: source, + }, + }, + settings: { + outputSelection: { + '*': { + '*': ['abi', 'evm.bytecode'], + }, + }, + }, }; - - console.log(`Compiling contract: ${basename(solidityFilePath)}...`); - + + console.log(`Compiling contract: ${fileName}...`); + // 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}`); - + const output = JSON.parse(solc.compile(JSON.stringify(input))); + + // Check for errors + if (output.errors) { + const errors = output.errors.filter(error => error.severity === 'error'); + if (errors.length > 0) { + console.error('Compilation errors:'); + errors.forEach(err => console.error(err.formattedMessage)); + return; + } + // Show warnings + const warnings = output.errors.filter(error => error.severity === 'warning'); + warnings.forEach(warn => console.warn(warn.formattedMessage)); + } + + // Ensure output directories exist + ensureDir(abiDir); + ensureDir(artifactsDir); + + // Process compiled contracts + for (const [sourceFile, contracts] of Object.entries(output.contracts)) { + for (const [contractName, contract] of Object.entries(contracts)) { + console.log(`Compiled contract: ${contractName}`); + // Write the ABI - const abiPath = join(outputDir, `${name}.json`); + const abiPath = join(abiDir, `${contractName}.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'), - ); + const bytecodePath = join(artifactsDir, `${contractName}.bin`); + writeFileSync(bytecodePath, contract.evm.bytecode.object); console.log(`Bytecode saved to ${bytecodePath}`); } } @@ -217,134 +259,287 @@ const compileContract = async (solidityFilePath, outputDir) => { } }; -const solidityFilePath = './Storage.sol'; -const outputDir = '.'; - -compileContract(solidityFilePath, outputDir); +const solidityFilePath = join(__dirname, '../contracts/Storage.sol'); +const abiDir = join(__dirname, '../abis'); +const artifactsDir = join(__dirname, '../artifacts'); +compileContract(solidityFilePath, abiDir, artifactsDir); ``` -To compile your contract, simply run the following command: +!!! 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 +node scripts/compile.js ``` -After compilation, you'll have two key files: an ABI (`.json`) file, which provides a JSON interface describing the contract's functions and how to interact with it, and a bytecode (`.polkavm`) file, which contains the low-level machine code executable on PolkaVM that represents the compiled smart contract ready for blockchain deployment. +After executing the script, the Solidity contract is compiled into standard EVM bytecode. The ABI and bytecode are saved into files with `.json` and `.bin` extensions, respectively. You can now proceed with deploying the contract to Polkadot Hub, as outlined in the next section. -## Contract Deployment +## Deploy the Compiled Contract -To deploy your compiled contract to Polkadot Hub using Web3.js, you'll need an account with a private key to sign the deployment transaction. The deployment process is exactly the same as for any Ethereum-compatible chain, involving creating a contract instance, estimating gas, and sending a deployment transaction. Here's how to deploy the contract, ensure replacing the `INSERT_RPC_URL`, `INSERT_PRIVATE_KEY`, and `INSERT_CONTRACT_NAME` with the appropriate values: +To deploy your compiled contract to Polkadot Hub, you'll need a wallet with a private key to sign the deployment transaction. -```javascript title="scripts/deploy.js" -import { readFileSync } from 'fs'; -import { Web3 } from 'web3'; +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: -const getAbi = (contractName) => { - try { - return JSON.parse(readFileSync(`${contractName}.json`), 'utf8'); - } catch (error) { - console.error( - `❌ Could not find ABI for contract ${contractName}:`, - error.message - ); - throw error; - } -}; +1. Set up the required imports and utilities: -const getByteCode = (contractName) => { - try { - return `0x${readFileSync(`${contractName}.polkavm`).toString('hex')}`; - } catch (error) { - console.error( - `❌ Could not find bytecode for contract ${contractName}:`, - error.message - ); - throw error; - } -}; + ```js title="scripts/deploy.js" + const { writeFileSync, existsSync, readFileSync } = require('fs'); + const { join } = require('path'); + const { Web3 } = require('web3'); -export const deploy = async (config) => { - try { - // Initialize Web3 with RPC URL - const web3 = new Web3(config.rpcUrl); + const scriptsDir = __dirname; + const abisDir = join(__dirname, '../abis'); + const artifactsDir = join(__dirname, '../artifacts'); + ``` - // Prepare account - const account = web3.eth.accounts.privateKeyToAccount(config.privateKey); - web3.eth.accounts.wallet.add(account); +2. Create a provider to connect to Polkadot Hub: - // Load abi - const abi = getAbi('Storage'); + ```js title="scripts/deploy.js" + const createProvider = (rpcUrl, chainId, chainName) => { + const web3 = new Web3(rpcUrl); + return web3; + }; + ``` - // Create contract instance - const contract = new web3.eth.Contract(abi); +3. Set up functions to read contract artifacts: - // Prepare deployment - const deployTransaction = contract.deploy({ - data: getByteCode('Storage'), - arguments: [], // Add constructor arguments if needed - }); + ```js title="scripts/deploy.js" + const getAbi = (contractName) => { + try { + const abiPath = join(abisDir, `${contractName}.json`); + return JSON.parse(readFileSync(abiPath, 'utf8')); + } catch (error) { + console.error( + `Could not find ABI for contract ${contractName}:`, + error.message, + ); + throw error; + } + }; - // Estimate gas - const gasEstimate = await deployTransaction.estimateGas({ - from: account.address, - }); + const getByteCode = (contractName) => { + try { + const bytecodePath = join(artifactsDir, `${contractName}.bin`); + const bytecode = readFileSync(bytecodePath, 'utf8').trim(); + return bytecode.startsWith('0x') ? bytecode : `0x${bytecode}`; + } catch (error) { + console.error( + `Could not find bytecode for contract ${contractName}:`, + error.message, + ); + throw error; + } + }; + ``` - // Get current gas price - const gasPrice = await web3.eth.getGasPrice(); +4. Create the main deployment function: - // Send deployment transaction - const deployedContract = await deployTransaction.send({ - from: account.address, - gas: gasEstimate, - gasPrice: gasPrice, - }); + ```js title="scripts/deploy.js" + const deployContract = async (contractName, privateKey, providerConfig) => { + console.log(`Deploying ${contractName}...`); + try { + const web3 = createProvider( + providerConfig.rpc, + providerConfig.chainId, + providerConfig.name, + ); - // Log and return contract details - console.log(`Contract deployed at: ${deployedContract.options.address}`); - return deployedContract; - } catch (error) { - console.error('Deployment failed:', error); - throw error; - } -}; + const formattedPrivateKey = privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`; + const account = web3.eth.accounts.privateKeyToAccount(formattedPrivateKey); + web3.eth.accounts.wallet.add(account); + web3.eth.defaultAccount = account.address; -// Example usage -const deploymentConfig = { - rpcUrl: 'INSERT_RPC_URL', - privateKey: 'INSERT_PRIVATE_KEY', - contractName: 'INSERT_CONTRACT_NAME', -}; + const abi = getAbi(contractName); + const bytecode = getByteCode(contractName); + const contract = new web3.eth.Contract(abi); + const deployTx = contract.deploy({ + data: bytecode, + }); -deploy(deploymentConfig) - .then((contract) => console.log('Deployment successful')) - .catch((error) => console.error('Deployment error')); + const gas = await deployTx.estimateGas(); + const gasPrice = await web3.eth.getGasPrice(); -``` + console.log(`Estimated gas: ${gas}`); + console.log(`Gas price: ${web3.utils.fromWei(gasPrice, 'gwei')} gwei`); + + const deployedContract = await deployTx.send({ + from: account.address, + gas: gas, + gasPrice: gasPrice, + }); + + const address = deployedContract.options.address; + console.log(`Contract ${contractName} deployed at: ${address}`); + + const addressesFile = join(scriptsDir, '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', // TODO: replace to `https://services.polkadothub-rpc.com/testnet` when ready + chainId: 420420422, + name: 'polkadot-hub-testnet', + }; + + const privateKey = 'INSERT_PRIVATE_KEY'; + + deployContract('Storage', privateKey, providerConfig); + ``` + + !!! note + + A private key is a hexadecimal string that is used to sign and pay for the deployment transaction. **Always keep your private key secure and never share it publicly**. + + Ensure to replace the `INSERT_PRIVATE_KEY` placeholder with your actual private key. + +??? code "View complete script" + + ```js title="scripts/deploy.js" + const { writeFileSync, existsSync, readFileSync } = require('fs'); + const { join } = require('path'); + const { Web3 } = require('web3'); + + const scriptsDir = __dirname; + const abisDir = join(__dirname, '../abis'); + const artifactsDir = join(__dirname, '../artifacts'); + + const createProvider = (rpcUrl, chainId, chainName) => { + const web3 = new Web3(rpcUrl); + return web3; + }; + + const getAbi = (contractName) => { + try { + const abiPath = join(abisDir, `${contractName}.json`); + return JSON.parse(readFileSync(abiPath, 'utf8')); + } catch (error) { + console.error( + `Could not find ABI for contract ${contractName}:`, + error.message, + ); + throw error; + } + }; + + const getByteCode = (contractName) => { + try { + const bytecodePath = join(artifactsDir, `${contractName}.bin`); + const bytecode = readFileSync(bytecodePath, 'utf8').trim(); + return bytecode.startsWith('0x') ? bytecode : `0x${bytecode}`; + } catch (error) { + console.error( + `Could not find bytecode for contract ${contractName}:`, + error.message, + ); + throw error; + } + }; + + const deployContract = async (contractName, privateKey, providerConfig) => { + console.log(`Deploying ${contractName}...`); + try { + const web3 = createProvider( + providerConfig.rpc, + providerConfig.chainId, + providerConfig.name, + ); + + const formattedPrivateKey = privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`; + const account = web3.eth.accounts.privateKeyToAccount(formattedPrivateKey); + web3.eth.accounts.wallet.add(account); + web3.eth.defaultAccount = account.address; + + const abi = getAbi(contractName); + const bytecode = getByteCode(contractName); + const contract = new web3.eth.Contract(abi); + const deployTx = contract.deploy({ + data: bytecode, + }); + + const gas = await deployTx.estimateGas(); + const gasPrice = await web3.eth.getGasPrice(); + + console.log(`Estimated gas: ${gas}`); + console.log(`Gas price: ${web3.utils.fromWei(gasPrice, 'gwei')} gwei`); + + const deployedContract = await deployTx.send({ + from: account.address, + gas: gas, + gasPrice: gasPrice, + }); + + const address = deployedContract.options.address; + console.log(`Contract ${contractName} deployed at: ${address}`); + + const addressesFile = join(scriptsDir, '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', // TODO: replace to `https://services.polkadothub-rpc.com/testnet` when ready + chainId: 420420422, + name: 'polkadot-hub-testnet', + }; -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}. + const privateKey = 'INSERT_PRIVATE_KEY'; -To deploy your contract, run the following command: + deployContract('Storage', privateKey, providerConfig); + + + ``` + +To run the script, execute the following command: ```bash -node deploy +node scripts/deploy.js ``` +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 deployed, you can interact with your contract using Web3.js methods. Here's how to set a number and read it back, ensure replacing `INSERT_RPC_URL`, `INSERT_PRIVATE_KEY`, and `INSERT_CONTRACT_ADDRESS` with the appropriate values: +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 `updateStorage.js` in the root of your project and add the following code: -```javascript title="scripts/updateStorage.js" -import { readFileSync } from 'fs'; -import { Web3 } from 'web3'; +```js title="scripts/updateStorage.js" +const { readFileSync } = require('fs'); +const { join } = require('path'); +const { Web3 } = require('web3'); + +const abisDir = join(__dirname, '../abis'); const getAbi = (contractName) => { try { - return JSON.parse(readFileSync(`${contractName}.json`), 'utf8'); + const abiPath = join(abisDir, `${contractName}.json`); + return JSON.parse(readFileSync(abiPath, 'utf8')); } catch (error) { console.error( - `❌ Could not find ABI for contract ${contractName}:`, - error.message + `Could not find ABI for contract ${contractName}:`, + error.message, ); throw error; } @@ -352,45 +547,31 @@ const getAbi = (contractName) => { const updateStorage = async (config) => { try { - // Initialize Web3 with RPC URL const web3 = new Web3(config.rpcUrl); - - // Prepare account - const account = web3.eth.accounts.privateKeyToAccount(config.privateKey); + const formattedPrivateKey = config.privateKey.startsWith('0x') ? config.privateKey : `0x${config.privateKey}`; + const account = web3.eth.accounts.privateKeyToAccount(formattedPrivateKey); web3.eth.accounts.wallet.add(account); - // Load abi const abi = getAbi('Storage'); - - // Create contract instance const contract = new web3.eth.Contract(abi, config.contractAddress); - // Get initial value const initialValue = await contract.methods.storedNumber().call(); console.log('Current stored value:', initialValue); - // Prepare transaction const updateTransaction = contract.methods.setNumber(1); - - // Estimate gas const gasEstimate = await updateTransaction.estimateGas({ from: account.address, }); - - // Get current gas price const gasPrice = await web3.eth.getGasPrice(); - // Send update transaction const receipt = await updateTransaction.send({ from: account.address, gas: gasEstimate, gasPrice: gasPrice, }); - // Log transaction details console.log(`Transaction hash: ${receipt.transactionHash}`); - // Get updated value const newValue = await contract.methods.storedNumber().call(); console.log('New stored value:', newValue); @@ -401,9 +582,8 @@ const updateStorage = async (config) => { } }; -// Example usage const config = { - rpcUrl: 'INSERT_RPC_URL', + rpcUrl: 'https://testnet-passet-hub-eth-rpc.polkadot.io', privateKey: 'INSERT_PRIVATE_KEY', contractAddress: 'INSERT_CONTRACT_ADDRESS', }; @@ -411,18 +591,22 @@ const config = { updateStorage(config) .then((receipt) => console.log('Update successful')) .catch((error) => console.error('Update error')); - ``` -To execute the logic above, run: +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. The script prints the balance for `ADDRESS_TO_CHECK` before it writes and doubles the stored value, so pick any account you want to monitor. + +To interact with the contract, run: ```bash -node updateStorage +node scripts/updateStorage.js ``` ## Where to Go Next -Now that you’ve learned how to use Web3.js with Polkadot Hub, explore more advanced topics: +Now that you have the foundational knowledge to use Web3.js with Polkadot Hub, you can: + +- **Dive into Web3.js utilities**: Discover additional Web3.js features, such as wallet management, signing messages, subscribing to events, etc. + +- **Implement batch transactions**: Use Web3.js to execute batch transactions for efficient multi-step contract interactions. -- **Utilize Web3.js utilities**: Learn about additional [Web3.js](https://docs.web3js.org/){target=\_blank} features such as signing transactions, managing wallets, and subscribing to events. -- **Build full-stack dApps**: [integrate Web3.js](https://docs.web3js.org/guides/dapps/intermediate-dapp){target=\_blank} with different libraries and frameworks to build decentralized web applications. +- **Build scalable applications**: Combine Web3.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). diff --git a/.ai/site-index.json b/.ai/site-index.json index 66fe0f3ff..ee3940c56 100644 --- a/.ai/site-index.json +++ b/.ai/site-index.json @@ -8720,7 +8720,7 @@ }, { "id": "smart-contracts-libraries-web3-js", - "title": "Web3.js", + "title": "Deploy Contracts to Polkadot Hub with Web3.js", "slug": "smart-contracts-libraries-web3-js", "categories": [ "Smart Contracts", @@ -8728,7 +8728,7 @@ ], "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.", + "preview": "!!! 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, @@ -8765,10 +8765,20 @@ "title": "Compile Contracts", "anchor": "compile-contracts" }, + { + "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": "Contract Deployment", - "anchor": "contract-deployment" + "title": "Deploy the Compiled Contract", + "anchor": "deploy-the-compiled-contract" }, { "depth": 2, @@ -8782,12 +8792,12 @@ } ], "stats": { - "chars": 13266, - "words": 1579, - "headings": 10, - "estimated_token_count_total": 3035 + "chars": 20552, + "words": 2326, + "headings": 12, + "estimated_token_count_total": 4656 }, - "hash": "sha256:f0d36333d0d3afff7f6374a61d0f6d1fb878c9ef4c4e4c24447745661dbe59d0", + "hash": "sha256:4b94081bbb31a17d62c515b617c846ce87ff82d7af5e8b732326e13ed7c767d5", "token_estimator": "heuristic-v1" }, { diff --git a/.snippets/code/smart-contracts/libraries/web3-js/compile.js b/.snippets/code/smart-contracts/libraries/web3-js/compile.js index 2bd5a4350..ec13f81ba 100644 --- a/.snippets/code/smart-contracts/libraries/web3-js/compile.js +++ b/.snippets/code/smart-contracts/libraries/web3-js/compile.js @@ -1,37 +1,71 @@ -const { compile } = require('@parity/resolc'); -const { readFileSync, writeFileSync } = require('fs'); +const solc = require('solc'); +const { readFileSync, writeFileSync, mkdirSync, existsSync } = require('fs'); const { basename, join } = require('path'); -const compileContract = async (solidityFilePath, outputDir) => { +const ensureDir = (dirPath) => { + if (!existsSync(dirPath)) { + mkdirSync(dirPath, { recursive: true }); + } +}; + +const compileContract = (solidityFilePath, abiDir, artifactsDir) => { try { // Read the Solidity file const source = readFileSync(solidityFilePath, 'utf8'); - - // Construct the input object for the compiler + const fileName = basename(solidityFilePath); + + // Construct the input object for the Solidity compiler const input = { - [basename(solidityFilePath)]: { content: source }, + language: 'Solidity', + sources: { + [fileName]: { + content: source, + }, + }, + settings: { + outputSelection: { + '*': { + '*': ['abi', 'evm.bytecode'], + }, + }, + }, }; - - console.log(`Compiling contract: ${basename(solidityFilePath)}...`); - + + console.log(`Compiling contract: ${fileName}...`); + // 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}`); + const output = JSON.parse(solc.compile(JSON.stringify(input))); + + // Check for errors + if (output.errors) { + const errors = output.errors.filter(error => error.severity === 'error'); + if (errors.length > 0) { + console.error('Compilation errors:'); + errors.forEach(err => console.error(err.formattedMessage)); + return; + } + // Show warnings + const warnings = output.errors.filter(error => error.severity === 'warning'); + warnings.forEach(warn => console.warn(warn.formattedMessage)); + } + + // Ensure output directories exist + ensureDir(abiDir); + ensureDir(artifactsDir); + // Process compiled contracts + for (const [sourceFile, contracts] of Object.entries(output.contracts)) { + for (const [contractName, contract] of Object.entries(contracts)) { + console.log(`Compiled contract: ${contractName}`); + // Write the ABI - const abiPath = join(outputDir, `${name}.json`); + const abiPath = join(abiDir, `${contractName}.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'), - ); + const bytecodePath = join(artifactsDir, `${contractName}.bin`); + writeFileSync(bytecodePath, contract.evm.bytecode.object); console.log(`Bytecode saved to ${bytecodePath}`); } } @@ -40,7 +74,8 @@ const compileContract = async (solidityFilePath, outputDir) => { } }; -const solidityFilePath = './Storage.sol'; -const outputDir = '.'; +const solidityFilePath = join(__dirname, '../contracts/Storage.sol'); +const abiDir = join(__dirname, '../abis'); +const artifactsDir = join(__dirname, '../artifacts'); -compileContract(solidityFilePath, outputDir); +compileContract(solidityFilePath, abiDir, artifactsDir); \ No newline at end of file diff --git a/.snippets/code/smart-contracts/libraries/web3-js/deploy.js b/.snippets/code/smart-contracts/libraries/web3-js/deploy.js index 37fac5da1..ba7293e1b 100644 --- a/.snippets/code/smart-contracts/libraries/web3-js/deploy.js +++ b/.snippets/code/smart-contracts/libraries/web3-js/deploy.js @@ -1,13 +1,24 @@ -import { readFileSync } from 'fs'; -import { Web3 } from 'web3'; +const { writeFileSync, existsSync, readFileSync } = require('fs'); +const { join } = require('path'); +const { Web3 } = require('web3'); + +const scriptsDir = __dirname; +const abisDir = join(__dirname, '../abis'); +const artifactsDir = join(__dirname, '../artifacts'); + +const createProvider = (rpcUrl, chainId, chainName) => { + const web3 = new Web3(rpcUrl); + return web3; +}; const getAbi = (contractName) => { try { - return JSON.parse(readFileSync(`${contractName}.json`), 'utf8'); + const abiPath = join(abisDir, `${contractName}.json`); + return JSON.parse(readFileSync(abiPath, 'utf8')); } catch (error) { console.error( - `❌ Could not find ABI for contract ${contractName}:`, - error.message + `Could not find ABI for contract ${contractName}:`, + error.message, ); throw error; } @@ -15,68 +26,73 @@ const getAbi = (contractName) => { const getByteCode = (contractName) => { try { - return `0x${readFileSync(`${contractName}.polkavm`).toString('hex')}`; + const bytecodePath = join(artifactsDir, `${contractName}.bin`); + const bytecode = readFileSync(bytecodePath, 'utf8').trim(); + return bytecode.startsWith('0x') ? bytecode : `0x${bytecode}`; } catch (error) { console.error( - `❌ Could not find bytecode for contract ${contractName}:`, - error.message + `Could not find bytecode for contract ${contractName}:`, + error.message, ); throw error; } }; -export const deploy = async (config) => { +const deployContract = async (contractName, privateKey, providerConfig) => { + console.log(`Deploying ${contractName}...`); try { - // Initialize Web3 with RPC URL - const web3 = new Web3(config.rpcUrl); + const web3 = createProvider( + providerConfig.rpc, + providerConfig.chainId, + providerConfig.name, + ); - // Prepare account - const account = web3.eth.accounts.privateKeyToAccount(config.privateKey); + const formattedPrivateKey = privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`; + const account = web3.eth.accounts.privateKeyToAccount(formattedPrivateKey); web3.eth.accounts.wallet.add(account); + web3.eth.defaultAccount = account.address; - // Load abi - const abi = getAbi('Storage'); - - // Create contract instance + const abi = getAbi(contractName); + const bytecode = getByteCode(contractName); const contract = new web3.eth.Contract(abi); - - // Prepare deployment - const deployTransaction = contract.deploy({ - data: getByteCode('Storage'), - arguments: [], // Add constructor arguments if needed + const deployTx = contract.deploy({ + data: bytecode, }); - // Estimate gas - const gasEstimate = await deployTransaction.estimateGas({ - from: account.address, - }); - - // Get current gas price + const gas = await deployTx.estimateGas(); const gasPrice = await web3.eth.getGasPrice(); - // Send deployment transaction - const deployedContract = await deployTransaction.send({ + console.log(`Estimated gas: ${gas}`); + console.log(`Gas price: ${web3.utils.fromWei(gasPrice, 'gwei')} gwei`); + + const deployedContract = await deployTx.send({ from: account.address, - gas: gasEstimate, + gas: gas, gasPrice: gasPrice, }); - // Log and return contract details - console.log(`Contract deployed at: ${deployedContract.options.address}`); - return deployedContract; + const address = deployedContract.options.address; + console.log(`Contract ${contractName} deployed at: ${address}`); + + const addressesFile = join(scriptsDir, '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('Deployment failed:', error); - throw error; + console.error(`Failed to deploy contract ${contractName}:`, error); } }; -// Example usage -const deploymentConfig = { - rpcUrl: 'INSERT_RPC_URL', - privateKey: 'INSERT_PRIVATE_KEY', - contractName: 'INSERT_CONTRACT_NAME', +const providerConfig = { + rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', // TODO: replace to `https://services.polkadothub-rpc.com/testnet` when ready + chainId: 420420422, + name: 'polkadot-hub-testnet', }; -deploy(deploymentConfig) - .then((contract) => console.log('Deployment successful')) - .catch((error) => console.error('Deployment error')); +const privateKey = 'INSERT_PRIVATE_KEY'; + +deployContract('Storage', privateKey, providerConfig); + diff --git a/.snippets/code/smart-contracts/libraries/web3-js/updateStorage.js b/.snippets/code/smart-contracts/libraries/web3-js/updateStorage.js index f515eace3..6fff61593 100644 --- a/.snippets/code/smart-contracts/libraries/web3-js/updateStorage.js +++ b/.snippets/code/smart-contracts/libraries/web3-js/updateStorage.js @@ -1,13 +1,17 @@ -import { readFileSync } from 'fs'; -import { Web3 } from 'web3'; +const { readFileSync } = require('fs'); +const { join } = require('path'); +const { Web3 } = require('web3'); + +const abisDir = join(__dirname, '../abis'); const getAbi = (contractName) => { try { - return JSON.parse(readFileSync(`${contractName}.json`), 'utf8'); + const abiPath = join(abisDir, `${contractName}.json`); + return JSON.parse(readFileSync(abiPath, 'utf8')); } catch (error) { console.error( - `❌ Could not find ABI for contract ${contractName}:`, - error.message + `Could not find ABI for contract ${contractName}:`, + error.message, ); throw error; } @@ -15,45 +19,31 @@ const getAbi = (contractName) => { const updateStorage = async (config) => { try { - // Initialize Web3 with RPC URL const web3 = new Web3(config.rpcUrl); - - // Prepare account - const account = web3.eth.accounts.privateKeyToAccount(config.privateKey); + const formattedPrivateKey = config.privateKey.startsWith('0x') ? config.privateKey : `0x${config.privateKey}`; + const account = web3.eth.accounts.privateKeyToAccount(formattedPrivateKey); web3.eth.accounts.wallet.add(account); - // Load abi const abi = getAbi('Storage'); - - // Create contract instance const contract = new web3.eth.Contract(abi, config.contractAddress); - // Get initial value const initialValue = await contract.methods.storedNumber().call(); console.log('Current stored value:', initialValue); - // Prepare transaction const updateTransaction = contract.methods.setNumber(1); - - // Estimate gas const gasEstimate = await updateTransaction.estimateGas({ from: account.address, }); - - // Get current gas price const gasPrice = await web3.eth.getGasPrice(); - // Send update transaction const receipt = await updateTransaction.send({ from: account.address, gas: gasEstimate, gasPrice: gasPrice, }); - // Log transaction details console.log(`Transaction hash: ${receipt.transactionHash}`); - // Get updated value const newValue = await contract.methods.storedNumber().call(); console.log('New stored value:', newValue); @@ -64,13 +54,12 @@ const updateStorage = async (config) => { } }; -// Example usage const config = { - rpcUrl: 'INSERT_RPC_URL', + rpcUrl: 'https://testnet-passet-hub-eth-rpc.polkadot.io', privateKey: 'INSERT_PRIVATE_KEY', contractAddress: 'INSERT_CONTRACT_ADDRESS', }; updateStorage(config) .then((receipt) => console.log('Update successful')) - .catch((error) => console.error('Update error')); + .catch((error) => console.error('Update error')); \ No newline at end of file diff --git a/llms-full.jsonl b/llms-full.jsonl index 643cef3d9..67bb54d51 100644 --- a/llms-full.jsonl +++ b/llms-full.jsonl @@ -1146,16 +1146,18 @@ {"page_id": "smart-contracts-libraries-wagmi", "page_title": "Wagmi for Polkadot Hub Smart Contracts", "index": 7, "depth": 2, "title": "Interact with Deployed Contract", "anchor": "interact-with-deployed-contract", "start_char": 6700, "end_char": 11209, "estimated_token_count": 989, "token_estimator": "heuristic-v1", "text": "## Interact with Deployed Contract\n\nThis guide uses a simple Storage contract already deployed to the Polkadot Hub TestNet (`0x58053f0e8ede1a47a1af53e43368cd04ddcaf66f`). The code of that contract is:\n\n??? code \"Storage.sol\"\n\n ```solidity title=\"Storage.sol\"\n //SPDX-License-Identifier: MIT\n\n // Solidity files have to start with this pragma.\n // It will be used by the Solidity compiler to validate its version.\n pragma solidity ^0.8.9;\n\n contract Storage {\n // Public state variable to store a number\n uint256 public storedNumber;\n\n /**\n * Updates the stored number.\n *\n * The `public` modifier allows anyone to call this function.\n *\n * @param _newNumber - The new value to store.\n */\n function setNumber(uint256 _newNumber) public {\n storedNumber = _newNumber;\n }\n }\n ```\n\nCreate a component to interact with your deployed contract. Create a file named `app/components/StorageContract.tsx`:\n\n```typescript title=\"app/components/StorageContract.tsx\"\n\"use client\";\n\nimport { useState } from \"react\";\nimport {\n useReadContract,\n useWriteContract,\n useWaitForTransactionReceipt,\n} from \"wagmi\";\n\nconst CONTRACT_ADDRESS =\n \"0xabBd46Ef74b88E8B1CDa49BeFb5057710443Fd29\" as `0x${string}`;\n\nexport function StorageContract() {\n const [number, setNumber] = useState(\"42\");\n\n // Contract ABI (should match your compiled contract)\n const abi = [\n {\n inputs: [],\n name: \"storedNumber\",\n outputs: [{ internalType: \"uint256\", name: \"\", type: \"uint256\" }],\n stateMutability: \"view\",\n type: \"function\",\n },\n {\n inputs: [\n { internalType: \"uint256\", name: \"_newNumber\", type: \"uint256\" },\n ],\n name: \"setNumber\",\n outputs: [],\n stateMutability: \"nonpayable\",\n type: \"function\",\n },\n ];\n\n // Read the current stored number\n const { data: storedNumber, refetch } = useReadContract({\n address: CONTRACT_ADDRESS,\n abi,\n functionName: \"storedNumber\",\n });\n\n // Write to the contract\n const { writeContract, data: hash, error, isPending } = useWriteContract();\n\n // Wait for transaction to be mined\n const { isLoading: isConfirming, isSuccess: isConfirmed } =\n useWaitForTransactionReceipt({\n hash,\n });\n\n const handleSetNumber = () => {\n writeContract({\n address: CONTRACT_ADDRESS,\n abi,\n functionName: \"setNumber\",\n args: [BigInt(number)],\n });\n };\n\n return (\n
\n

Storage Contract Interaction

\n
\n

Contract Address: {CONTRACT_ADDRESS}

\n

Current Stored Number: {storedNumber?.toString() || \"Loading...\"}

\n
\n\n
\n setNumber(e.target.value)}\n disabled={isPending || isConfirming}\n />\n \n
\n\n {error &&
Error: {error.message}
}\n\n {isConfirmed && (\n
\n Successfully updated!{\" \"}\n \n
\n )}\n
\n );\n}\n\n```\n\nThis component demonstrates how to interact with a smart contract using Wagmi's hooks:\n\n- **[`useReadContract`](https://wagmi.sh/react/api/hooks/useReadContract#useReadContract){target=\\_blank}**: Calls a read-only function on your smart contract to retrieve data without modifying the blockchain state.\n- **[`useWriteContract`](https://wagmi.sh/react/api/hooks/useWriteContract#useWriteContract){target=\\_blank}**: Calls a state-modifying function on your smart contract, which requires a transaction to be signed and sent.\n- **[`useWaitForTransactionReceipt`](https://wagmi.sh/react/api/hooks/useWaitForTransactionReceipt#useWaitForTransactionReceipt){target=\\_blank}**: Tracks the status of a transaction after it's been submitted, allowing you to know when it's been confirmed.\n\nThe component also includes proper state handling to:\n\n- Show the current value stored in the contract.\n- Allow users to input a new value.\n- Display transaction status (pending, confirming, or completed).\n- Handle errors.\n- Provide feedback when a transaction is successful."} {"page_id": "smart-contracts-libraries-wagmi", "page_title": "Wagmi for Polkadot Hub Smart Contracts", "index": 8, "depth": 2, "title": "Integrate Components", "anchor": "integrate-components", "start_char": 11209, "end_char": 11961, "estimated_token_count": 183, "token_estimator": "heuristic-v1", "text": "## Integrate Components\n\nUpdate your main page to combine all the components. Create or update the file `src/app/page.tsx`:\n\n```typescript title=\"src/app/page.tsx\"\n\"use client\";\n\nimport { BlockchainInfo } from \"./components/BlockchainInfo\";\nimport { ConnectWallet } from \"./components/ConnectWallet\";\nimport { StorageContract } from \"./components/StorageContract\";\nimport { useAccount } from \"wagmi\";\n\nexport default function Home() {\n const { isConnected } = useAccount();\n\n return (\n
\n

Wagmi - Polkadot Hub Smart Contracts

\n \n {isConnected ? : Connect your wallet}\n {isConnected ? : Connect your wallet}\n
\n );\n}\n\n```"} {"page_id": "smart-contracts-libraries-wagmi", "page_title": "Wagmi for Polkadot Hub Smart Contracts", "index": 9, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 11961, "end_char": 13604, "estimated_token_count": 512, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nNow that you have the foundational knowledge to use Wagmi with Polkadot Hub, consider exploring:\n\n
\n\n- External __Advanced Wagmi__\n\n ---\n\n Explore Wagmi's advanced features:\n\n
    \n
  • [:octicons-arrow-right-24: Watch Contract Events](https://wagmi.sh/core/api/actions/watchContractEvent#eventname){target=\\_blank}
  • \n
  • [:octicons-arrow-right-24: Different Transports](https://wagmi.sh/react/api/transports){target=\\_blank}
  • \n
  • [:octicons-arrow-right-24: Actions](https://wagmi.sh/react/api/actions){target=\\_blank}
  • \n
\n\n- External __Wallet Integration__\n\n ---\n\n Connect your dApp with popular wallet providers:\n\n
    \n
  • [:octicons-arrow-right-24: MetaMask](https://wagmi.sh/core/api/connectors/metaMask){target=\\_blank}
  • \n
  • [:octicons-arrow-right-24: WalletConnect](https://wagmi.sh/core/api/connectors/walletConnect){target=\\_blank}
  • \n
  • [:octicons-arrow-right-24: Coinbase Wallet](https://wagmi.sh/core/api/connectors/coinbaseWallet){target=\\_blank}
  • \n
\n\n- External __Testing & Development__\n\n ---\n\n Enhance your development workflow:\n\n
    \n
  • [:octicons-arrow-right-24: Test Suite](https://wagmi.sh/dev/contributing#_6-running-the-test-suite){target=\\_blank}
  • \n
  • [:octicons-arrow-right-24: Dev Playground](https://wagmi.sh/dev/contributing#_5-running-the-dev-playgrounds){target=\\_blank}
  • \n
\n
"} -{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Web3.js", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 468, "end_char": 1027, "estimated_token_count": 102, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nInteracting with blockchains typically requires an interface between your application and the network. [Web3.js](https://web3js.readthedocs.io/){target=\\_blank} offers this interface through a comprehensive collection of libraries, facilitating seamless interaction with the nodes using HTTP or WebSocket protocols. This guide illustrates how to utilize Web3.js specifically for interactions with Polkadot Hub.\n\nThis guide is intended for developers who are familiar with JavaScript and want to interact with the Polkadot Hub using Web3.js."} -{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Web3.js", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 1027, "end_char": 1383, "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-web3-js", "page_title": "Web3.js", "index": 2, "depth": 2, "title": "Project Structure", "anchor": "project-structure", "start_char": 1383, "end_char": 1868, "estimated_token_count": 136, "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=\"Web3.js Polkadot Hub\"\nweb3js-project\n├── contracts\n│ ├── Storage.sol\n├── scripts\n│ ├── connectToProvider.js\n│ ├── fetchLastBlock.js\n│ ├── compile.js\n│ ├── deploy.js\n│ ├── updateStorage.js\n├── abis\n│ ├── Storage.json\n├── artifacts\n│ ├── Storage.polkavm\n├── node_modules/\n├── package.json\n├── package-lock.json\n└── README.md\n```"} -{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Web3.js", "index": 3, "depth": 2, "title": "Set Up the Project", "anchor": "set-up-the-project", "start_char": 1868, "end_char": 1984, "estimated_token_count": 31, "token_estimator": "heuristic-v1", "text": "## Set Up the Project\n\nTo start working with Web3.js, begin by initializing your project:\n\n```bash\nnpm init -y\n```"} -{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Web3.js", "index": 4, "depth": 2, "title": "Install Dependencies", "anchor": "install-dependencies", "start_char": 1984, "end_char": 2117, "estimated_token_count": 38, "token_estimator": "heuristic-v1", "text": "## Install Dependencies\n\nNext, install the Web3.js library:\n\n```bash\nnpm install web3\n```\n\nThis guide uses `web3` version `4.16.0`."} -{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Web3.js", "index": 5, "depth": 2, "title": "Set Up the Web3 Provider", "anchor": "set-up-the-web3-provider", "start_char": 2117, "end_char": 3950, "estimated_token_count": 425, "token_estimator": "heuristic-v1", "text": "## Set Up the Web3 Provider\n\nThe provider configuration is the foundation of any Web3.js application. The following example establishes a connection to Polkadot Hub. To use the example script, replace `INSERT_RPC_URL`, `INSERT_CHAIN_ID`, and `INSERT_CHAIN_NAME` with the appropriate values. The provider connection script should look something like this:\n\n```javascript title=\"scripts/connectToProvider.js\"\nconst { Web3 } = require('web3');\n\nconst createProvider = (rpcUrl) => {\n const web3 = new Web3(rpcUrl);\n return web3;\n};\n\nconst PROVIDER_RPC = {\n rpc: 'INSERT_RPC_URL',\n chainId: 'INSERT_CHAIN_ID',\n name: 'INSERT_CHAIN_NAME',\n};\n\ncreateProvider(PROVIDER_RPC.rpc);\n\n```\n\nFor example, for the Polkadot Hub TestNet, use these specific connection parameters:\n\n```js\nconst PROVIDER_RPC = {\n rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io',\n chainId: 420420422,\n name: 'polkadot-hub-testnet'\n};\n```\n\nWith the Web3 provider set up, you can start querying the blockchain.\n\nFor instance, to fetch the latest block number of the chain, you can use the following code snippet:\n\n???+ code \"View complete script\"\n\n ```javascript title=\"scripts/fetchLastBlock.js\"\n const { Web3 } = require('web3');\n\n const createProvider = (rpcUrl) => {\n const web3 = new Web3(rpcUrl);\n return web3;\n };\n\n const PROVIDER_RPC = {\n rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io',\n chainId: 420420422,\n name: 'polkadot-hub-testnet',\n };\n\n const main = async () => {\n try {\n const web3 = createProvider(PROVIDER_RPC.rpc);\n const latestBlock = await web3.eth.getBlockNumber();\n console.log('Last block: ' + latestBlock);\n } catch (error) {\n console.error('Error connecting to Polkadot Hub TestNet: ' + error.message);\n }\n };\n\n main();\n\n ```"} -{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Web3.js", "index": 6, "depth": 2, "title": "Compile Contracts", "anchor": "compile-contracts", "start_char": 3950, "end_char": 7431, "estimated_token_count": 840, "token_estimator": "heuristic-v1", "text": "## Compile Contracts\n\n!!! note \"Contracts Code Blob Size Disclaimer\"\n The maximum contract code blob size on Polkadot Hub networks is _100 kilobytes_, significantly larger than Ethereum’s EVM limit of 24 kilobytes.\n\n 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.\n\nPolkadot Hub requires contracts to be compiled to [PolkaVM](/smart-contracts/for-eth-devs/dual-vm-stack/){target=\\_blank} bytecode. This is achieved using the [`revive`](https://github.com/paritytech/revive/tree/v0.2.0/js/resolc){target=\\_blank} compiler. Install the [`@parity/resolc`](https://github.com/paritytech/revive){target=\\_blank} library as a development dependency:\n\n```bash\nnpm install --save-dev @parity/resolc\n```\n\nThis guide uses `@parity/resolc` version `0.2.0`.\n\nHere's a simple storage contract that you can use to follow the process:\n\n```solidity title=\"contracts/Storage.sol\"\n//SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\ncontract Storage {\n // Public state variable to store a number\n uint256 public storedNumber;\n\n /**\n * Updates the stored number.\n *\n * The `public` modifier allows anyone to call this function.\n *\n * @param _newNumber - The new value to store.\n */\n function setNumber(uint256 _newNumber) public {\n storedNumber = _newNumber;\n }\n}\n```\n\nWith that, you can now create a `compile.js` snippet that transforms your solidity code into PolkaVM bytecode:\n\n```javascript title=\"scripts/compile.js\"\nconst { compile } = require('@parity/resolc');\nconst { readFileSync, writeFileSync } = require('fs');\nconst { basename, join } = require('path');\n\nconst compileContract = async (solidityFilePath, outputDir) => {\n try {\n // Read the Solidity file\n const source = readFileSync(solidityFilePath, 'utf8');\n\n // Construct the input object for the compiler\n const input = {\n [basename(solidityFilePath)]: { content: source },\n };\n\n console.log(`Compiling contract: ${basename(solidityFilePath)}...`);\n\n // Compile the contract\n const out = await compile(input);\n\n for (const contracts of Object.values(out.contracts)) {\n for (const [name, contract] of Object.entries(contracts)) {\n console.log(`Compiled contract: ${name}`);\n\n // Write the ABI\n const abiPath = join(outputDir, `${name}.json`);\n writeFileSync(abiPath, JSON.stringify(contract.abi, null, 2));\n console.log(`ABI saved to ${abiPath}`);\n\n // Write the bytecode\n const bytecodePath = join(outputDir, `${name}.polkavm`);\n writeFileSync(\n bytecodePath,\n Buffer.from(contract.evm.bytecode.object, 'hex'),\n );\n console.log(`Bytecode saved to ${bytecodePath}`);\n }\n }\n } catch (error) {\n console.error('Error compiling contracts:', error);\n }\n};\n\nconst solidityFilePath = './Storage.sol';\nconst outputDir = '.';\n\ncompileContract(solidityFilePath, outputDir);\n\n```\n\nTo compile your contract, simply run the following command:\n\n```bash\nnode compile\n```\n\nAfter compilation, you'll have two key files: an ABI (`.json`) file, which provides a JSON interface describing the contract's functions and how to interact with it, and a bytecode (`.polkavm`) file, which contains the low-level machine code executable on PolkaVM that represents the compiled smart contract ready for blockchain deployment."} -{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Web3.js", "index": 7, "depth": 2, "title": "Contract Deployment", "anchor": "contract-deployment", "start_char": 7431, "end_char": 10374, "estimated_token_count": 674, "token_estimator": "heuristic-v1", "text": "## Contract Deployment\n\nTo deploy your compiled contract to Polkadot Hub using Web3.js, you'll need an account with a private key to sign the deployment transaction. The deployment process is exactly the same as for any Ethereum-compatible chain, involving creating a contract instance, estimating gas, and sending a deployment transaction. Here's how to deploy the contract, ensure replacing the `INSERT_RPC_URL`, `INSERT_PRIVATE_KEY`, and `INSERT_CONTRACT_NAME` with the appropriate values:\n\n```javascript title=\"scripts/deploy.js\"\nimport { readFileSync } from 'fs';\nimport { Web3 } from 'web3';\n\nconst getAbi = (contractName) => {\n try {\n return JSON.parse(readFileSync(`${contractName}.json`), 'utf8');\n } catch (error) {\n console.error(\n `❌ Could not find ABI for contract ${contractName}:`,\n error.message\n );\n throw error;\n }\n};\n\nconst getByteCode = (contractName) => {\n try {\n return `0x${readFileSync(`${contractName}.polkavm`).toString('hex')}`;\n } catch (error) {\n console.error(\n `❌ Could not find bytecode for contract ${contractName}:`,\n error.message\n );\n throw error;\n }\n};\n\nexport const deploy = async (config) => {\n try {\n // Initialize Web3 with RPC URL\n const web3 = new Web3(config.rpcUrl);\n\n // Prepare account\n const account = web3.eth.accounts.privateKeyToAccount(config.privateKey);\n web3.eth.accounts.wallet.add(account);\n\n // Load abi\n const abi = getAbi('Storage');\n\n // Create contract instance\n const contract = new web3.eth.Contract(abi);\n\n // Prepare deployment\n const deployTransaction = contract.deploy({\n data: getByteCode('Storage'),\n arguments: [], // Add constructor arguments if needed\n });\n\n // Estimate gas\n const gasEstimate = await deployTransaction.estimateGas({\n from: account.address,\n });\n\n // Get current gas price\n const gasPrice = await web3.eth.getGasPrice();\n\n // Send deployment transaction\n const deployedContract = await deployTransaction.send({\n from: account.address,\n gas: gasEstimate,\n gasPrice: gasPrice,\n });\n\n // Log and return contract details\n console.log(`Contract deployed at: ${deployedContract.options.address}`);\n return deployedContract;\n } catch (error) {\n console.error('Deployment failed:', error);\n throw error;\n }\n};\n\n// Example usage\nconst deploymentConfig = {\n rpcUrl: 'INSERT_RPC_URL',\n privateKey: 'INSERT_PRIVATE_KEY',\n contractName: 'INSERT_CONTRACT_NAME',\n};\n\ndeploy(deploymentConfig)\n .then((contract) => console.log('Deployment successful'))\n .catch((error) => console.error('Deployment error'));\n\n```\n\nFor 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\nTo deploy your contract, run the following command:\n\n```bash\nnode deploy\n```"} -{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Web3.js", "index": 8, "depth": 2, "title": "Interact with the Contract", "anchor": "interact-with-the-contract", "start_char": 10374, "end_char": 12757, "estimated_token_count": 548, "token_estimator": "heuristic-v1", "text": "## Interact with the Contract\n\nOnce deployed, you can interact with your contract using Web3.js methods. Here's how to set a number and read it back, ensure replacing `INSERT_RPC_URL`, `INSERT_PRIVATE_KEY`, and `INSERT_CONTRACT_ADDRESS` with the appropriate values:\n\n```javascript title=\"scripts/updateStorage.js\"\nimport { readFileSync } from 'fs';\nimport { Web3 } from 'web3';\n\nconst getAbi = (contractName) => {\n try {\n return JSON.parse(readFileSync(`${contractName}.json`), 'utf8');\n } catch (error) {\n console.error(\n `❌ Could not find ABI for contract ${contractName}:`,\n error.message\n );\n throw error;\n }\n};\n\nconst updateStorage = async (config) => {\n try {\n // Initialize Web3 with RPC URL\n const web3 = new Web3(config.rpcUrl);\n\n // Prepare account\n const account = web3.eth.accounts.privateKeyToAccount(config.privateKey);\n web3.eth.accounts.wallet.add(account);\n\n // Load abi\n const abi = getAbi('Storage');\n\n // Create contract instance\n const contract = new web3.eth.Contract(abi, config.contractAddress);\n\n // Get initial value\n const initialValue = await contract.methods.storedNumber().call();\n console.log('Current stored value:', initialValue);\n\n // Prepare transaction\n const updateTransaction = contract.methods.setNumber(1);\n\n // Estimate gas\n const gasEstimate = await updateTransaction.estimateGas({\n from: account.address,\n });\n\n // Get current gas price\n const gasPrice = await web3.eth.getGasPrice();\n\n // Send update transaction\n const receipt = await updateTransaction.send({\n from: account.address,\n gas: gasEstimate,\n gasPrice: gasPrice,\n });\n\n // Log transaction details\n console.log(`Transaction hash: ${receipt.transactionHash}`);\n\n // Get updated value\n const newValue = await contract.methods.storedNumber().call();\n console.log('New stored value:', newValue);\n\n return receipt;\n } catch (error) {\n console.error('Update failed:', error);\n throw error;\n }\n};\n\n// Example usage\nconst config = {\n rpcUrl: 'INSERT_RPC_URL',\n privateKey: 'INSERT_PRIVATE_KEY',\n contractAddress: 'INSERT_CONTRACT_ADDRESS',\n};\n\nupdateStorage(config)\n .then((receipt) => console.log('Update successful'))\n .catch((error) => console.error('Update error'));\n\n```\n\nTo execute the logic above, run:\n\n```bash\nnode updateStorage\n```"} -{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Web3.js", "index": 9, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 12757, "end_char": 13266, "estimated_token_count": 131, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nNow that you’ve learned how to use Web3.js with Polkadot Hub, explore more advanced topics:\n\n- **Utilize Web3.js utilities**: Learn about additional [Web3.js](https://docs.web3js.org/){target=\\_blank} features such as signing transactions, managing wallets, and subscribing to events.\n- **Build full-stack dApps**: [integrate Web3.js](https://docs.web3js.org/guides/dapps/intermediate-dapp){target=\\_blank} with different libraries and frameworks to build decentralized web applications."} +{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 298, "end_char": 857, "estimated_token_count": 102, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nInteracting with blockchains typically requires an interface between your application and the network. [Web3.js](https://web3js.readthedocs.io/){target=\\_blank} offers this interface through a comprehensive collection of libraries, facilitating seamless interaction with the nodes using HTTP or WebSocket protocols. This guide illustrates how to utilize Web3.js specifically for interactions with Polkadot Hub.\n\nThis guide is intended for developers who are familiar with JavaScript and want to interact with the Polkadot Hub using Web3.js."} +{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 857, "end_char": 1213, "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-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 2, "depth": 2, "title": "Project Structure", "anchor": "project-structure", "start_char": 1213, "end_char": 1720, "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=\"Web3.js Polkadot Hub\"\nweb3js-project\n├── contracts\n│ ├── Storage.sol\n├── scripts\n│ ├── connectToProvider.js\n│ ├── fetchLastBlock.js\n│ ├── compile.js\n│ ├── deploy.js\n│ ├── updateStorage.js\n├── abis\n│ ├── Storage.json\n├── artifacts\n│ ├── Storage.bin\n├── contract-address.json\n├── node_modules/\n├── package.json\n├── package-lock.json\n└── README.md\n```"} +{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 3, "depth": 2, "title": "Set Up the Project", "anchor": "set-up-the-project", "start_char": 1720, "end_char": 1939, "estimated_token_count": 50, "token_estimator": "heuristic-v1", "text": "## Set Up the Project\n\nTo start working with Web3.js, create a new folder and initialize your project by running the following commands in your terminal:\n\n```bash\nmkdir web3js-project\ncd web3js-project\nnpm init -y\n```"} +{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 4, "depth": 2, "title": "Install Dependencies", "anchor": "install-dependencies", "start_char": 1939, "end_char": 2352, "estimated_token_count": 107, "token_estimator": "heuristic-v1", "text": "## Install Dependencies\n\nNext, run the following command to install the Web3.js library:\n\n```bash\nnpm install web3\n```\n\nAdd the Solidity compiler so you can generate standard EVM bytecode:\n\n```bash\nnpm install --save-dev solc\n```\n\n!!! tip\n The sample scripts use ECMAScript modules. Add `\"type\": \"module\"` to your `package.json` (or rename the files to `.mjs`) so that `node` can run the `import` statements."} +{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 5, "depth": 2, "title": "Set Up the Web3 Provider", "anchor": "set-up-the-web3-provider", "start_char": 2352, "end_char": 4539, "estimated_token_count": 501, "token_estimator": "heuristic-v1", "text": "## Set Up the Web3 Provider\n\nThe provider configuration is the foundation of any Web3.js application. It serves as a bridge between your application and the blockchain, allowing you to query blockchain data and interact with smart contracts.\n\nTo interact with Polkadot Hub, you must set up a Web3.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:\n\n```js title=\"scripts/connectToProvider.js\"\nconst { Web3 } = require('web3');\n\nconst createProvider = (rpcUrl) => {\n const web3 = new Web3(rpcUrl);\n return web3;\n};\n\nconst PROVIDER_RPC = {\n rpc: 'INSERT_RPC_URL',\n chainId: 'INSERT_CHAIN_ID',\n name: 'INSERT_CHAIN_NAME',\n};\n\ncreateProvider(PROVIDER_RPC.rpc);\n\n```\n\n!!! note\n 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:\n\n ```js\n const PROVIDER_RPC = {\n rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io',\n chainId: 420420422,\n name: 'polkadot-hub-testnet'\n };\n ```\n\nTo connect to the provider, execute:\n\n```bash\nnode scripts/connectToProvider.js\n```\n\nWith the provider set up, you can start querying the blockchain. For instance, to fetch the latest block number:\n\n??? code \"Fetch Last Block code\"\n\n ```js title=\"scripts/fetchLastBlock.js\"\n const { Web3 } = require('web3');\n\n const createProvider = (rpcUrl) => {\n const web3 = new Web3(rpcUrl);\n return web3;\n };\n\n const PROVIDER_RPC = {\n rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io',\n chainId: 420420422,\n name: 'polkadot-hub-testnet',\n };\n\n const main = async () => {\n try {\n const web3 = createProvider(PROVIDER_RPC.rpc);\n const latestBlock = await web3.eth.getBlockNumber();\n console.log('Last block: ' + latestBlock);\n } catch (error) {\n console.error('Error connecting to Polkadot Hub TestNet: ' + error.message);\n }\n };\n\n main();\n\n ```"} +{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 6, "depth": 2, "title": "Compile Contracts", "anchor": "compile-contracts", "start_char": 4539, "end_char": 4866, "estimated_token_count": 74, "token_estimator": "heuristic-v1", "text": "## Compile Contracts\n\nPolkadot Hub exposes an Ethereum JSON-RPC endpoint, so you can compile Solidity contracts to familiar EVM bytecode with the upstream [`solc`](https://www.npmjs.com/package/solc){target=\\_blank} compiler. The resulting artifacts work with any EVM-compatible toolchain and can be deployed through Web3.js."} +{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 7, "depth": 3, "title": "Sample Storage Smart Contract", "anchor": "sample-storage-smart-contract", "start_char": 4866, "end_char": 5571, "estimated_token_count": 145, "token_estimator": "heuristic-v1", "text": "### Sample Storage Smart Contract\n\nThis 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.\n\n```solidity title=\"contracts/Storage.sol\"\n//SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\ncontract Storage {\n // Public state variable to store a number\n uint256 public storedNumber;\n\n /**\n * Updates the stored number.\n *\n * The `public` modifier allows anyone to call this function.\n *\n * @param _newNumber - The new value to store.\n */\n function setNumber(uint256 _newNumber) public {\n storedNumber = _newNumber;\n }\n}\n```"} +{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 8, "depth": 3, "title": "Compile the Smart Contract", "anchor": "compile-the-smart-contract", "start_char": 5571, "end_char": 9128, "estimated_token_count": 810, "token_estimator": "heuristic-v1", "text": "### Compile the Smart Contract\n\nTo compile this contract, use the following script:\n\n```js title=\"scripts/compile.js\"\nconst solc = require('solc');\nconst { readFileSync, writeFileSync, mkdirSync, existsSync } = require('fs');\nconst { basename, join } = require('path');\n\nconst ensureDir = (dirPath) => {\n if (!existsSync(dirPath)) {\n mkdirSync(dirPath, { recursive: true });\n }\n};\n\nconst compileContract = (solidityFilePath, abiDir, artifactsDir) => {\n try {\n // Read the Solidity file\n const source = readFileSync(solidityFilePath, 'utf8');\n const fileName = basename(solidityFilePath);\n \n // Construct the input object for the Solidity compiler\n const input = {\n language: 'Solidity',\n sources: {\n [fileName]: {\n content: source,\n },\n },\n settings: {\n outputSelection: {\n '*': {\n '*': ['abi', 'evm.bytecode'],\n },\n },\n },\n };\n \n console.log(`Compiling contract: ${fileName}...`);\n \n // Compile the contract\n const output = JSON.parse(solc.compile(JSON.stringify(input)));\n \n // Check for errors\n if (output.errors) {\n const errors = output.errors.filter(error => error.severity === 'error');\n if (errors.length > 0) {\n console.error('Compilation errors:');\n errors.forEach(err => console.error(err.formattedMessage));\n return;\n }\n // Show warnings\n const warnings = output.errors.filter(error => error.severity === 'warning');\n warnings.forEach(warn => console.warn(warn.formattedMessage));\n }\n \n // Ensure output directories exist\n ensureDir(abiDir);\n ensureDir(artifactsDir);\n\n // Process compiled contracts\n for (const [sourceFile, contracts] of Object.entries(output.contracts)) {\n for (const [contractName, contract] of Object.entries(contracts)) {\n console.log(`Compiled contract: ${contractName}`);\n \n // Write the ABI\n const abiPath = join(abiDir, `${contractName}.json`);\n writeFileSync(abiPath, JSON.stringify(contract.abi, null, 2));\n console.log(`ABI saved to ${abiPath}`);\n \n // Write the bytecode\n const bytecodePath = join(artifactsDir, `${contractName}.bin`);\n writeFileSync(bytecodePath, contract.evm.bytecode.object);\n console.log(`Bytecode saved to ${bytecodePath}`);\n }\n }\n } catch (error) {\n console.error('Error compiling contracts:', error);\n }\n};\n\nconst solidityFilePath = join(__dirname, '../contracts/Storage.sol');\nconst abiDir = join(__dirname, '../abis');\nconst artifactsDir = join(__dirname, '../artifacts');\n\ncompileContract(solidityFilePath, abiDir, artifactsDir);\n```\n\n!!! note \n 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.\n\nThe 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.\n\nExecute the script above by running:\n\n```bash\nnode scripts/compile.js\n```\n\nAfter executing the script, the Solidity contract is compiled into standard EVM bytecode. The ABI and bytecode are saved into files with `.json` and `.bin` extensions, respectively. You can now proceed with deploying the contract to Polkadot Hub, as outlined in the next section."} +{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 9, "depth": 2, "title": "Deploy the Compiled Contract", "anchor": "deploy-the-compiled-contract", "start_char": 9128, "end_char": 17197, "estimated_token_count": 1798, "token_estimator": "heuristic-v1", "text": "## Deploy the Compiled Contract\n\nTo deploy your compiled contract to Polkadot Hub, you'll need a wallet with a private key to sign the deployment transaction.\n\nYou can create a `deploy.js` script in the root of your project to achieve this. The deployment script can be divided into key components:\n\n1. Set up the required imports and utilities:\n\n ```js title=\"scripts/deploy.js\"\n const { writeFileSync, existsSync, readFileSync } = require('fs');\n const { join } = require('path');\n const { Web3 } = require('web3');\n\n const scriptsDir = __dirname;\n const abisDir = join(__dirname, '../abis');\n const artifactsDir = join(__dirname, '../artifacts');\n ```\n\n2. Create a provider to connect to Polkadot Hub:\n\n ```js title=\"scripts/deploy.js\"\n const createProvider = (rpcUrl, chainId, chainName) => {\n const web3 = new Web3(rpcUrl);\n return web3;\n };\n ```\n\n3. Set up functions to read contract artifacts:\n\n ```js title=\"scripts/deploy.js\"\n const getAbi = (contractName) => {\n try {\n const abiPath = join(abisDir, `${contractName}.json`);\n return JSON.parse(readFileSync(abiPath, 'utf8'));\n } catch (error) {\n console.error(\n `Could not find ABI for contract ${contractName}:`,\n error.message,\n );\n throw error;\n }\n };\n\n const getByteCode = (contractName) => {\n try {\n const bytecodePath = join(artifactsDir, `${contractName}.bin`);\n const bytecode = readFileSync(bytecodePath, 'utf8').trim();\n return bytecode.startsWith('0x') ? bytecode : `0x${bytecode}`;\n } catch (error) {\n console.error(\n `Could not find bytecode for contract ${contractName}:`,\n error.message,\n );\n throw error;\n }\n };\n ```\n\n4. Create the main deployment function:\n\n ```js title=\"scripts/deploy.js\"\n const deployContract = async (contractName, privateKey, providerConfig) => {\n console.log(`Deploying ${contractName}...`);\n try {\n const web3 = createProvider(\n providerConfig.rpc,\n providerConfig.chainId,\n providerConfig.name,\n );\n\n const formattedPrivateKey = privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`;\n const account = web3.eth.accounts.privateKeyToAccount(formattedPrivateKey);\n web3.eth.accounts.wallet.add(account);\n web3.eth.defaultAccount = account.address;\n\n const abi = getAbi(contractName);\n const bytecode = getByteCode(contractName);\n const contract = new web3.eth.Contract(abi);\n const deployTx = contract.deploy({\n data: bytecode,\n });\n\n const gas = await deployTx.estimateGas();\n const gasPrice = await web3.eth.getGasPrice();\n\n console.log(`Estimated gas: ${gas}`);\n console.log(`Gas price: ${web3.utils.fromWei(gasPrice, 'gwei')} gwei`);\n\n const deployedContract = await deployTx.send({\n from: account.address,\n gas: gas,\n gasPrice: gasPrice,\n });\n\n const address = deployedContract.options.address;\n console.log(`Contract ${contractName} deployed at: ${address}`);\n\n const addressesFile = join(scriptsDir, 'contract-address.json');\n const addresses = existsSync(addressesFile)\n ? JSON.parse(readFileSync(addressesFile, 'utf8'))\n : {};\n\n addresses[contractName] = address;\n writeFileSync(addressesFile, JSON.stringify(addresses, null, 2), 'utf8');\n } catch (error) {\n console.error(`Failed to deploy contract ${contractName}:`, error);\n }\n };\n ```\n\n5. Configure and execute the deployment:\n\n ```js title=\"scripts/deploy.js\"\n const providerConfig = {\n rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', // TODO: replace to `https://services.polkadothub-rpc.com/testnet` when ready\n chainId: 420420422,\n name: 'polkadot-hub-testnet',\n };\n\n const privateKey = 'INSERT_PRIVATE_KEY';\n\n deployContract('Storage', privateKey, providerConfig);\n ```\n\n !!! note\n\n A private key is a hexadecimal string that is used to sign and pay for the deployment transaction. **Always keep your private key secure and never share it publicly**.\n\n Ensure to replace the `INSERT_PRIVATE_KEY` placeholder with your actual private key.\n\n??? code \"View complete script\"\n\n ```js title=\"scripts/deploy.js\"\n const { writeFileSync, existsSync, readFileSync } = require('fs');\n const { join } = require('path');\n const { Web3 } = require('web3');\n\n const scriptsDir = __dirname;\n const abisDir = join(__dirname, '../abis');\n const artifactsDir = join(__dirname, '../artifacts');\n\n const createProvider = (rpcUrl, chainId, chainName) => {\n const web3 = new Web3(rpcUrl);\n return web3;\n };\n\n const getAbi = (contractName) => {\n try {\n const abiPath = join(abisDir, `${contractName}.json`);\n return JSON.parse(readFileSync(abiPath, 'utf8'));\n } catch (error) {\n console.error(\n `Could not find ABI for contract ${contractName}:`,\n error.message,\n );\n throw error;\n }\n };\n\n const getByteCode = (contractName) => {\n try {\n const bytecodePath = join(artifactsDir, `${contractName}.bin`);\n const bytecode = readFileSync(bytecodePath, 'utf8').trim();\n return bytecode.startsWith('0x') ? bytecode : `0x${bytecode}`;\n } catch (error) {\n console.error(\n `Could not find bytecode for contract ${contractName}:`,\n error.message,\n );\n throw error;\n }\n };\n\n const deployContract = async (contractName, privateKey, providerConfig) => {\n console.log(`Deploying ${contractName}...`);\n try {\n const web3 = createProvider(\n providerConfig.rpc,\n providerConfig.chainId,\n providerConfig.name,\n );\n\n const formattedPrivateKey = privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`;\n const account = web3.eth.accounts.privateKeyToAccount(formattedPrivateKey);\n web3.eth.accounts.wallet.add(account);\n web3.eth.defaultAccount = account.address;\n\n const abi = getAbi(contractName);\n const bytecode = getByteCode(contractName);\n const contract = new web3.eth.Contract(abi);\n const deployTx = contract.deploy({\n data: bytecode,\n });\n\n const gas = await deployTx.estimateGas();\n const gasPrice = await web3.eth.getGasPrice();\n\n console.log(`Estimated gas: ${gas}`);\n console.log(`Gas price: ${web3.utils.fromWei(gasPrice, 'gwei')} gwei`);\n\n const deployedContract = await deployTx.send({\n from: account.address,\n gas: gas,\n gasPrice: gasPrice,\n });\n\n const address = deployedContract.options.address;\n console.log(`Contract ${contractName} deployed at: ${address}`);\n\n const addressesFile = join(scriptsDir, 'contract-address.json');\n const addresses = existsSync(addressesFile)\n ? JSON.parse(readFileSync(addressesFile, 'utf8'))\n : {};\n\n addresses[contractName] = address;\n writeFileSync(addressesFile, JSON.stringify(addresses, null, 2), 'utf8');\n } catch (error) {\n console.error(`Failed to deploy contract ${contractName}:`, error);\n }\n };\n\n const providerConfig = {\n rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', // TODO: replace to `https://services.polkadothub-rpc.com/testnet` when ready\n chainId: 420420422,\n name: 'polkadot-hub-testnet',\n };\n\n const privateKey = 'INSERT_PRIVATE_KEY';\n\n deployContract('Storage', privateKey, providerConfig);\n\n\n ```\n\nTo run the script, execute the following command:\n\n```bash\nnode scripts/deploy.js\n```\n\nAfter 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."} +{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 10, "depth": 2, "title": "Interact with the Contract", "anchor": "interact-with-the-contract", "start_char": 17197, "end_char": 19932, "estimated_token_count": 656, "token_estimator": "heuristic-v1", "text": "## Interact with the Contract\n\nOnce 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 `updateStorage.js` in the root of your project and add the following code:\n\n```js title=\"scripts/updateStorage.js\"\nconst { readFileSync } = require('fs');\nconst { join } = require('path');\nconst { Web3 } = require('web3');\n\nconst abisDir = join(__dirname, '../abis');\n\nconst getAbi = (contractName) => {\n try {\n const abiPath = join(abisDir, `${contractName}.json`);\n return JSON.parse(readFileSync(abiPath, 'utf8'));\n } catch (error) {\n console.error(\n `Could not find ABI for contract ${contractName}:`,\n error.message,\n );\n throw error;\n }\n};\n\nconst updateStorage = async (config) => {\n try {\n const web3 = new Web3(config.rpcUrl);\n const formattedPrivateKey = config.privateKey.startsWith('0x') ? config.privateKey : `0x${config.privateKey}`;\n const account = web3.eth.accounts.privateKeyToAccount(formattedPrivateKey);\n web3.eth.accounts.wallet.add(account);\n\n const abi = getAbi('Storage');\n const contract = new web3.eth.Contract(abi, config.contractAddress);\n\n const initialValue = await contract.methods.storedNumber().call();\n console.log('Current stored value:', initialValue);\n\n const updateTransaction = contract.methods.setNumber(1);\n const gasEstimate = await updateTransaction.estimateGas({\n from: account.address,\n });\n const gasPrice = await web3.eth.getGasPrice();\n\n const receipt = await updateTransaction.send({\n from: account.address,\n gas: gasEstimate,\n gasPrice: gasPrice,\n });\n\n console.log(`Transaction hash: ${receipt.transactionHash}`);\n\n const newValue = await contract.methods.storedNumber().call();\n console.log('New stored value:', newValue);\n\n return receipt;\n } catch (error) {\n console.error('Update failed:', error);\n throw error;\n }\n};\n\nconst config = {\n rpcUrl: 'https://testnet-passet-hub-eth-rpc.polkadot.io',\n privateKey: 'INSERT_PRIVATE_KEY',\n contractAddress: 'INSERT_CONTRACT_ADDRESS',\n};\n\nupdateStorage(config)\n .then((receipt) => console.log('Update successful'))\n .catch((error) => console.error('Update error'));\n```\n\nEnsure 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. The script prints the balance for `ADDRESS_TO_CHECK` before it writes and doubles the stored value, so pick any account you want to monitor.\n\nTo interact with the contract, run:\n\n```bash\nnode scripts/updateStorage.js\n```"} +{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 11, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 19932, "end_char": 20552, "estimated_token_count": 159, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nNow that you have the foundational knowledge to use Web3.js with Polkadot Hub, you can:\n\n- **Dive into Web3.js utilities**: Discover additional Web3.js features, such as wallet management, signing messages, subscribing to events, etc.\n\n- **Implement batch transactions**: Use Web3.js to execute batch transactions for efficient multi-step contract interactions.\n\n- **Build scalable applications**: Combine Web3.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_id": "smart-contracts-libraries-web3-py", "page_title": "Web3.py", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 181, "end_char": 605, "estimated_token_count": 83, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nInteracting with blockchains typically requires an interface between your application and the network. [Web3.py](https://web3py.readthedocs.io/en/stable/index.html){target=\\_blank} offers this interface through a collection of libraries, facilitating seamless interaction with the nodes using HTTP or WebSocket protocols. \n\nThis guide illustrates how to utilize Web3.py for interactions with Polkadot Hub."} {"page_id": "smart-contracts-libraries-web3-py", "page_title": "Web3.py", "index": 1, "depth": 2, "title": "Set Up the Project", "anchor": "set-up-the-project", "start_char": 605, "end_char": 986, "estimated_token_count": 88, "token_estimator": "heuristic-v1", "text": "## Set Up the Project\n\n1. To start working with Web3.py, begin by initializing your project:\n\n ```bash\n mkdir web3py-project\n cd web3py-project\n ```\n\n2. Create and activate a virtual environment for your project:\n\n ```bash\n python -m venv venv\n source venv/bin/activate\n ```\n\n3. Next, install the Web3.py library:\n\n ```bash\n pip install web3\n ```"} {"page_id": "smart-contracts-libraries-web3-py", "page_title": "Web3.py", "index": 2, "depth": 2, "title": "Set Up the Web3 Provider", "anchor": "set-up-the-web3-provider", "start_char": 986, "end_char": 3080, "estimated_token_count": 423, "token_estimator": "heuristic-v1", "text": "## Set Up the Web3 Provider\n\nThe [provider](https://web3py.readthedocs.io/en/stable/providers.html){target=\\_blank} configuration is the foundation of any Web3.py application. The following example establishes a connection to Polkadot Hub. Follow these steps to use the provider configuration:\n\n1. Replace `INSERT_RPC_URL` with the appropriate value. For instance, to connect to Polkadot Hub TestNet, use the following parameter:\n\n ```python\n PROVIDER_RPC = 'https://testnet-passet-hub-eth-rpc.polkadot.io'\n ```\n\n The provider connection script should look something like this:\n\n ```python title=\"connect_to_provider.py\"\n from web3 import Web3\n\n def create_provider(rpc_url):\n web3 = Web3(Web3.HTTPProvider(rpc_url))\n return web3\n\n PROVIDER_RPC = 'INSERT_RPC_URL'\n\n create_provider(PROVIDER_RPC)\n ```\n\n1. With the Web3 provider set up, start querying the blockchain. For instance, you can use the following code snippet to fetch the latest block number of the chain:\n\n ```python title=\"fetch_last_block.py\"\n def main():\n try:\n web3 = create_provider(PROVIDER_RPC)\n latest_block = web3.eth.block_number\n print('Last block: ' + str(latest_block))\n except Exception as error:\n print('Error connecting to Polkadot Hub TestNet: ' + str(error))\n\n if __name__ == \"__main__\":\n main()\n ```\n\n ??? code \"View complete script\"\n\n ```python title=\"fetch_last_block.py\"\n from web3 import Web3\n\n def create_provider(rpc_url):\n web3 = Web3(Web3.HTTPProvider(rpc_url))\n return web3\n\n PROVIDER_RPC = 'https://testnet-passet-hub-eth-rpc.polkadot.io'\n\n def main():\n try:\n web3 = create_provider(PROVIDER_RPC)\n latest_block = web3.eth.block_number\n print('Last block: ' + str(latest_block))\n except Exception as error:\n print('Error connecting to Polkadot Hub TestNet: ' + str(error))\n\n if __name__ == \"__main__\":\n main()\n ```"} diff --git a/llms.txt b/llms.txt index 1b820afd6..2cf36421d 100644 --- a/llms.txt +++ b/llms.txt @@ -73,7 +73,7 @@ Docs: Smart Contracts - [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. - [viem for Polkadot Hub Smart Contracts](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-viem.md): This guide covers deploying and interacting with contracts on Polkadot Hub using viem, a TypeScript library for Ethereum-compatible chains. - [Wagmi for Polkadot Hub Smart Contracts](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-wagmi.md): Learn how to use Wagmi React Hooks to fetch and interact with smart contracts on Polkadot Hub for seamless dApp integration. -- [Web3.js](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-web3-js.md): Learn how to interact with Polkadot Hub using Web3.js, deploying Solidity contracts, and interacting with deployed smart contracts. +- [Deploy Contracts to Polkadot Hub with Web3.js](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-web3-js.md): Learn how to interact with Polkadot Hub using Web3.js, from compiling and deploying Solidity contracts to interacting with deployed smart contracts. - [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. - [Smart Contracts Overview](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-overview.md): Learn about smart contract development capabilities in the Polkadot ecosystem, either by leveraging Polkadot Hub or other alternatives. - [Ethereum-Native Precompiles](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles-eth-native.md): General overview of Ethereum-native precompiles in Polkadot Hub’s Revive pallet, including usage basics and details on standard precompiles for smart contracts. @@ -186,7 +186,7 @@ Docs: Tooling - [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. - [viem for Polkadot Hub Smart Contracts](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-viem.md): This guide covers deploying and interacting with contracts on Polkadot Hub using viem, a TypeScript library for Ethereum-compatible chains. - [Wagmi for Polkadot Hub Smart Contracts](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-wagmi.md): Learn how to use Wagmi React Hooks to fetch and interact with smart contracts on Polkadot Hub for seamless dApp integration. -- [Web3.js](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-web3-js.md): Learn how to interact with Polkadot Hub using Web3.js, deploying Solidity contracts, and interacting with deployed smart contracts. +- [Deploy Contracts to Polkadot Hub with Web3.js](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-web3-js.md): Learn how to interact with Polkadot Hub using Web3.js, from compiling and deploying Solidity contracts to interacting with deployed smart contracts. - [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 diff --git a/smart-contracts/libraries/web3-js.md b/smart-contracts/libraries/web3-js.md index 8c4545aa4..abc4bd194 100644 --- a/smart-contracts/libraries/web3-js.md +++ b/smart-contracts/libraries/web3-js.md @@ -1,13 +1,11 @@ --- -title: Web3.js -description: Learn how to interact with Polkadot Hub using Web3.js, deploying Solidity contracts, and interacting with deployed smart contracts. +title: Deploy Contracts to Polkadot Hub with Web3.js +description: Learn how to interact with Polkadot Hub using Web3.js, from compiling and deploying Solidity contracts to interacting with deployed smart contracts. categories: Smart Contracts, Tooling --- # Web3.js ---8<-- 'text/smart-contracts/polkaVM-warning.md' - !!! 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. @@ -42,7 +40,8 @@ web3js-project ├── abis │ ├── Storage.json ├── artifacts -│ ├── Storage.polkavm +│ ├── Storage.bin +├── contract-address.json ├── node_modules/ ├── package.json ├── package-lock.json @@ -51,115 +50,177 @@ web3js-project ## Set Up the Project -To start working with Web3.js, begin by initializing your project: +To start working with Web3.js, create a new folder and initialize your project by running the following commands in your terminal: ```bash +mkdir web3js-project +cd web3js-project npm init -y ``` ## Install Dependencies -Next, install the Web3.js library: +Next, run the following command to install the Web3.js library: ```bash npm install web3 ``` -This guide uses `web3` version `{{ dependencies.javascript_packages.web3_js.version }}`. +Add the Solidity compiler so you can generate standard EVM bytecode: + +```bash +npm install --save-dev solc +``` + +!!! tip + The sample scripts use ECMAScript modules. Add `"type": "module"` to your `package.json` (or rename the files to `.mjs`) so that `node` can run the `import` statements. ## Set Up the Web3 Provider -The provider configuration is the foundation of any Web3.js application. The following example establishes a connection to Polkadot Hub. To use the example script, replace `INSERT_RPC_URL`, `INSERT_CHAIN_ID`, and `INSERT_CHAIN_NAME` with the appropriate values. The provider connection script should look something like this: +The provider configuration is the foundation of any Web3.js application. It serves as a bridge between your application and the blockchain, allowing you to query blockchain data and interact with smart contracts. + +To interact with Polkadot Hub, you must set up a Web3.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: -```javascript title="scripts/connectToProvider.js" +```js title="scripts/connectToProvider.js" --8<-- 'code/smart-contracts/libraries/web3-js/connectToProvider.js' ``` -For example, for the Polkadot Hub TestNet, use these specific connection parameters: +!!! 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' -}; -``` + ```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: -With the Web3 provider set up, you can start querying the blockchain. +```bash +node scripts/connectToProvider.js +``` -For instance, to fetch the latest block number of the chain, you can use the following code snippet: +With the provider set up, you can start querying the blockchain. For instance, to fetch the latest block number: -???+ code "View complete script" +??? code "Fetch Last Block code" - ```javascript title="scripts/fetchLastBlock.js" + ```js title="scripts/fetchLastBlock.js" --8<-- 'code/smart-contracts/libraries/web3-js/fetchLastBlock.js' ``` ## Compile Contracts ---8<-- 'text/smart-contracts/code-size.md' +Polkadot Hub exposes an Ethereum JSON-RPC endpoint, so you can compile Solidity contracts to familiar EVM bytecode with the upstream [`solc`](https://www.npmjs.com/package/solc){target=\_blank} compiler. The resulting artifacts work with any EVM-compatible toolchain and can be deployed through Web3.js. -Polkadot Hub requires contracts to be compiled to [PolkaVM](/smart-contracts/for-eth-devs/dual-vm-stack/){target=\_blank} bytecode. This is achieved using the [`revive`](https://github.com/paritytech/revive/tree/v0.2.0/js/resolc){target=\_blank} compiler. Install the [`@parity/resolc`](https://github.com/paritytech/revive){target=\_blank} library as a development dependency: +### Sample Storage Smart Contract -```bash -npm install --save-dev @parity/resolc -``` - -This guide uses `@parity/resolc` version `{{ dependencies.javascript_packages.resolc.version }}`. - -Here's a simple storage contract that you can use to follow the process: +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" --8<-- 'code/smart-contracts/libraries/web3-js/Storage.sol' ``` -With that, you can now create a `compile.js` snippet that transforms your solidity code into PolkaVM bytecode: +### Compile the Smart Contract + +To compile this contract, use the following script: -```javascript title="scripts/compile.js" +```js title="scripts/compile.js" --8<-- 'code/smart-contracts/libraries/web3-js/compile.js' ``` -To compile your contract, simply run the following command: +!!! 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 +node scripts/compile.js ``` -After compilation, you'll have two key files: an ABI (`.json`) file, which provides a JSON interface describing the contract's functions and how to interact with it, and a bytecode (`.polkavm`) file, which contains the low-level machine code executable on PolkaVM that represents the compiled smart contract ready for blockchain deployment. +After executing the script, the Solidity contract is compiled into standard EVM bytecode. The ABI and bytecode are saved into files with `.json` and `.bin` extensions, respectively. You can now proceed with deploying the contract to Polkadot Hub, as outlined in the next section. -## Contract Deployment +## Deploy the Compiled Contract -To deploy your compiled contract to Polkadot Hub using Web3.js, you'll need an account with a private key to sign the deployment transaction. The deployment process is exactly the same as for any Ethereum-compatible chain, involving creating a contract instance, estimating gas, and sending a deployment transaction. Here's how to deploy the contract, ensure replacing the `INSERT_RPC_URL`, `INSERT_PRIVATE_KEY`, and `INSERT_CONTRACT_NAME` with the appropriate values: +To deploy your compiled contract to Polkadot Hub, you'll need a wallet with a private key to sign the deployment transaction. -```javascript title="scripts/deploy.js" ---8<-- 'code/smart-contracts/libraries/web3-js/deploy.js' -``` +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: -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}. +1. Set up the required imports and utilities: -To deploy your contract, run the following command: + ```js title="scripts/deploy.js" + --8<-- 'code/smart-contracts/libraries/web3-js/deploy.js:1:7' + ``` + +2. Create a provider to connect to Polkadot Hub: + + ```js title="scripts/deploy.js" + --8<-- 'code/smart-contracts/libraries/web3-js/deploy.js:9:12' + ``` + +3. Set up functions to read contract artifacts: + + ```js title="scripts/deploy.js" + --8<-- 'code/smart-contracts/libraries/web3-js/deploy.js:14:39' + ``` + +4. Create the main deployment function: + + ```js title="scripts/deploy.js" + --8<-- 'code/smart-contracts/libraries/web3-js/deploy.js:41:87' + ``` + +5. Configure and execute the deployment: + + ```js title="scripts/deploy.js" + --8<-- 'code/smart-contracts/libraries/web3-js/deploy.js:89:97' + ``` + + !!! note + + A private key is a hexadecimal string that is used to sign and pay for the deployment transaction. **Always keep your private key secure and never share it publicly**. + + Ensure to replace the `INSERT_PRIVATE_KEY` placeholder with your actual private key. + +??? code "View complete script" + + ```js title="scripts/deploy.js" + --8<-- 'code/smart-contracts/libraries/web3-js/deploy.js' + ``` + +To run the script, execute the following command: ```bash -node deploy +node scripts/deploy.js ``` +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 deployed, you can interact with your contract using Web3.js methods. Here's how to set a number and read it back, ensure replacing `INSERT_RPC_URL`, `INSERT_PRIVATE_KEY`, and `INSERT_CONTRACT_ADDRESS` with the appropriate values: +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 `updateStorage.js` in the root of your project and add the following code: -```javascript title="scripts/updateStorage.js" +```js title="scripts/updateStorage.js" --8<-- 'code/smart-contracts/libraries/web3-js/updateStorage.js' ``` -To execute the logic above, run: +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. The script prints the balance for `ADDRESS_TO_CHECK` before it writes and doubles the stored value, so pick any account you want to monitor. + +To interact with the contract, run: ```bash -node updateStorage +node scripts/updateStorage.js ``` ## Where to Go Next -Now that you’ve learned how to use Web3.js with Polkadot Hub, explore more advanced topics: +Now that you have the foundational knowledge to use Web3.js with Polkadot Hub, you can: + +- **Dive into Web3.js utilities**: Discover additional Web3.js features, such as wallet management, signing messages, subscribing to events, etc. + +- **Implement batch transactions**: Use Web3.js to execute batch transactions for efficient multi-step contract interactions. -- **Utilize Web3.js utilities**: Learn about additional [Web3.js](https://docs.web3js.org/){target=\_blank} features such as signing transactions, managing wallets, and subscribing to events. -- **Build full-stack dApps**: [integrate Web3.js](https://docs.web3js.org/guides/dapps/intermediate-dapp){target=\_blank} with different libraries and frameworks to build decentralized web applications. +- **Build scalable applications**: Combine Web3.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).