# Moonbeam Developer Documentation (LLMS Format)
This file contains documentation for Moonbeam (https://moonbeam.network/). Moonbeam is a smart contract platform that makes it easy to build natively interoperable applications on Polkadot and Ethereum.
It is intended for use with large language models (LLMs) to support developers working with Moonbeam. The content includes selected pages from the official docs, organized by section.
This file includes documentation related to the product: Substrate Toolkit
## AI Prompt Template
You are an AI developer assistant for Moonbeam (https://moonbeam.network/). Your task is to assist developers in understanding and using the product described in this file.
- Provide accurate answers based on the included documentation.
- Do not assume undocumented features, behaviors, or APIs.
- If unsure, respond with “Not specified in the documentation.
## List of doc pages:
Doc-Page: https://raw.githubusercontent.com/moonbeam-foundation/moonbeam-docs/refs/heads/master/builders/substrate/dev-env/chopsticks.md [type: builders]
Doc-Page: https://raw.githubusercontent.com/moonbeam-foundation/moonbeam-docs/refs/heads/master/builders/substrate/interfaces/account/identity.md [type: builders]
Doc-Page: https://raw.githubusercontent.com/moonbeam-foundation/moonbeam-docs/refs/heads/master/builders/substrate/interfaces/account/multisig.md [type: builders]
Doc-Page: https://raw.githubusercontent.com/moonbeam-foundation/moonbeam-docs/refs/heads/master/builders/substrate/interfaces/account/proxy.md [type: builders]
Doc-Page: https://raw.githubusercontent.com/moonbeam-foundation/moonbeam-docs/refs/heads/master/builders/substrate/interfaces/features/governance/conviction-voting.md [type: builders]
Doc-Page: https://raw.githubusercontent.com/moonbeam-foundation/moonbeam-docs/refs/heads/master/builders/substrate/interfaces/features/governance/parameters.md [type: builders]
Doc-Page: https://raw.githubusercontent.com/moonbeam-foundation/moonbeam-docs/refs/heads/master/builders/substrate/interfaces/features/governance/preimage.md [type: builders]
Doc-Page: https://raw.githubusercontent.com/moonbeam-foundation/moonbeam-docs/refs/heads/master/builders/substrate/interfaces/features/governance/referenda.md [type: builders]
Doc-Page: https://raw.githubusercontent.com/moonbeam-foundation/moonbeam-docs/refs/heads/master/builders/substrate/interfaces/features/randomness.md [type: builders]
Doc-Page: https://raw.githubusercontent.com/moonbeam-foundation/moonbeam-docs/refs/heads/master/builders/substrate/interfaces/features/staking.md [type: builders]
Doc-Page: https://raw.githubusercontent.com/moonbeam-foundation/moonbeam-docs/refs/heads/master/builders/substrate/interfaces/utility/utility.md [type: builders]
Doc-Page: https://raw.githubusercontent.com/moonbeam-foundation/moonbeam-docs/refs/heads/master/builders/substrate/libraries/polkadot-js-api.md [type: builders]
Doc-Page: https://raw.githubusercontent.com/moonbeam-foundation/moonbeam-docs/refs/heads/master/builders/substrate/libraries/py-substrate-interface.md [type: builders]
Doc-Page: https://raw.githubusercontent.com/moonbeam-foundation/moonbeam-docs/refs/heads/master/builders/substrate/libraries/sidecar.md [type: builders]
## Full content for each doc page
Doc-Content: https://docs.moonbeam.network/builders/substrate/dev-env/chopsticks/
--- BEGIN CONTENT ---
---
title: How to use Chopsticks to Fork Moonbeam
description: Learn the basics of how to use Chopsticks to replay blocks, dissect state changes, test XCM interactions, and locally fork the entirety of a Moonbeam network.
categories: Substrate Toolkit, Dev Environments
---
# How to Use Chopsticks to Fork Moonbeam
## Introduction {: #introduction }
[Chopsticks](https://github.com/AcalaNetwork/chopsticks){target=\_blank} provides a developer-friendly method of locally forking existing Substrate based chains. It allows for the replaying of blocks to easily examine how extrinsics affect state, the forking of multiple blocks for XCM testing, and more. This allows developers to test and experiment with their own custom blockchain configurations in a local development environment, without the need to deploy a live network.
Overall, Chopsticks aims to simplify the process of building blockchain applications on Substrate and make it accessible to a wider range of developers.
## Forking Moonbeam with Chopsticks {: #forking-moonbeam }
To use Chopsticks, you can install it as a package with the [Node package manager](https://nodejs.org/en){target=\_blank} or [Yarn](https://yarnpkg.com){target=\_blank}:
```bash
npm i @acala-network/chopsticks@latest
```
Once installed, you can run commands with the Node package executor. For example, this runs Chopstick's base command:
```bash
npx @acala-network/chopsticks@latest
```
To run Chopsticks, you will need some sort of configuration, typically through a file. Chopsticks' source repository includes a set of [YAML](https://yaml.org){target=\_blank} configuration files that can be used to create a local copy of a variety of Substrate chains. You can download the configuration files from the [source repository's `configs` folder](https://github.com/AcalaNetwork/chopsticks){target=\_blank}.
Moonbeam, Moonriver, and Moonbase Alpha all have default files available:
=== "Moonbeam"
```yaml
endpoint: wss://wss.api.moonbeam.network
mock-signature-host: true
db: ./db.sqlite
import-storage:
System:
Account:
-
-
- "0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"
- data:
free: "100000000000000000000000"
TechCommitteeCollective:
Members: ["0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"]
CouncilCollective:
Members: ["0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"]
TreasuryCouncilCollective:
Members: ["0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"]
AuthorFilter:
EligibleRatio: 100
EligibleCount: 100
```
=== "Moonriver"
```yaml
endpoint: wss://wss.moonriver.moonbeam.network
mock-signature-host: true
db: ./db.sqlite
import-storage:
System:
Account:
-
-
- "0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"
- data:
free: "100000000000000000000000"
TechCommitteeCollective:
Members: ["0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"]
CouncilCollective:
Members: ["0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"]
TreasuryCouncilCollective:
Members: ["0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"]
AuthorFilter:
EligibleRatio: 100
EligibleCount: 100
```
=== "Moonbase Alpha"
```yaml
endpoint: wss://wss.api.moonbase.moonbeam.network
mock-signature-host: true
db: ./db.sqlite
import-storage:
System:
Account:
-
-
- "0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"
- data:
free: "100000000000000000000000"
TechCommitteeCollective:
Members: ["0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"]
CouncilCollective:
Members: ["0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"]
TreasuryCouncilCollective:
Members: ["0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"]
Sudo:
Key: "0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"
AuthorFilter:
EligibleRatio: 100
EligibleCount: 100
```
These are the settings that can be included in the config file:
| Option | Description |
|:--------------------------:|:------------------------------------------------------------------------------------------------------------:|
| `genesis` | The link to a parachain's raw genesis file to build the fork from, instead of an endpoint. |
| `timestamp` | Timestamp of the block to fork from. |
| `endpoint` | The endpoint of the parachain to fork. |
| `block` | Use to specify at which block hash or number to replay the fork. |
| `wasm-override` | Path of the WASM to use as the parachain runtime, instead of an endpoint's runtime. |
| `db` | Path to the name of the file that stores or will store the parachain's database. |
| `config` | Path or URL of the config file. |
| `port` | The port to expose an endpoint on. |
| `build-block-mode` | How blocks should be built in the fork: batch, manual, instant. |
| `import-storage` | A pre-defined JSON/YAML storage file path to override in the parachain's storage. |
| `allow-unresolved-imports` | Whether to allow WASM unresolved imports when using a WASM to build the parachain. |
| `html` | Include to generate storage diff preview between blocks. |
| `mock-signature-host` | Mock signature host so that any signature starts with `0xdeadbeef` and filled by `0xcd` is considered valid. |
You can use the configuration file with the base command `npx @acala-network/chopsticks@latest` to fork assets by providing it with the `--config` flag.
You can use a raw GitHub URL of the default configuration files, a path to a local configuration file, or simply use the chain's name for the `--config` flag. For example, the following commands all use Moonbeam's configuration in the same way:
=== "Chain Name"
```bash
npx @acala-network/chopsticks@latest --config=moonbeam
```
=== "GitHub URL"
```bash
npx @acala-network/chopsticks@latest \
--config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/moonbeam.yml
```
=== "Local File Path"
```bash
npx @acala-network/chopsticks@latest --config=configs/moonbeam.yml
```
!!! note
If using a file path, make sure you've downloaded the [Moonbeam configuration file](https://github.com/AcalaNetwork/chopsticks/blob/master/configs/moonbeam.yml){target=\_blank}, or have created your own.
A configuration file is not necessary, however. All of the settings (except `genesis` and `timestamp`) can also be passed as flags to configure the environment completely in the command line. For example, the following command forks Moonbase Alpha at block 100.
```bash
npx @acala-network/chopsticks@latest --endpoint {{ networks.moonbase.wss_url }} --block 100
```
### Quickstart {: #quickstart }
The simplest way to fork Moonbeam is through the configuration files that are stored in the Chopsticks GitHub repository:
=== "Moonbeam"
```bash
npx @acala-network/chopsticks@latest \
--config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/moonbeam.yml
```
=== "Moonriver"
```bash
npx @acala-network/chopsticks@latest \
--config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/moonriver.yml
```
=== "Moonbase Alpha"
```bash
npx @acala-network/chopsticks@latest \
--config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/moonbase-alpha.yml
```
### Interacting with a Fork {: #interacting-with-a-fork }
When running a fork, by default it will be accessible at:
```text
ws://localhost:8000
```
You will be able to interact with the parachain via libraries such as [Polkadot.js](https://github.com/polkadot-js/common){target=\_blank} and its [user interface, Polkadot.js Apps](https://github.com/polkadot-js/apps){target=\_blank}.
You can interact with Chopsticks via the [Polkadot.js Apps hosted user interface](https://polkadot.js.org/apps/#/explorer){target=\_blank}. To do so, visit the page and take the following steps:
1. Click the icon in the top left
2. Go to the bottom and open **Development**
3. Select the **Custom** endpoint and enter `ws://localhost:8000`
4. Click the **Switch** button


You should now be able to interact with the fork as you would an active parachain or relay chain.
!!! note
If your browser cannot connect to the WebSocket endpoint provided by Chopsticks, you might need to allow insecure connections for the Polkadot.js Apps URL. Another solution is to run the [Docker version of Polkadot.js Apps](https://github.com/polkadot-js/apps#docker){target=\_blank}.
## Replaying Blocks {: #replaying-blocks }
In the case where you would like to replay a block and retrieve its information to dissect the effects of an extrinsic, you can use the `npx @acala-network/chopsticks@latest run-block` command. Its following flags are:
| Flag | Description |
|:--------------------------:|:--------------------------------------------------------------------------------------:|
| `endpoint` | The endpoint of the parachain to fork. |
| `block` | Use to specify at which block hash or number to replay the fork. |
| `wasm-override` | Path of the WASM to use as the parachain runtime, instead of an endpoint's runtime. |
| `db` | Path to the name of the file that stores or will store the parachain's database. |
| `config` | Path or URL of the config file. |
| `output-path=/[file_path]` | Use to print out results to a JSON file instead of printing it out in the console. |
| `html` | Include to generate an HTML representation of the storage diff preview between blocks. |
| `open` | Whether to open the HTML representation. |
For example, running the following command will re-run Moonbeam's block 1000, and write the storage diff and other data in a `moonbeam-output.json` file:
```bash
npx @acala-network/chopsticks@latest run-block \
--endpoint wss://wss.api.moonbeam.network \
--output-path=./moonbeam-output.json \
--block 1000
```
## XCM Testing {: #xcm-testing }
To test out XCM messages between networks, you can fork multiple parachains and a relay chain locally. For example, the following will fork Moonriver, Karura, and Kusama given that you've downloaded the [`configs` directory from the source GitHub repository](https://github.com/AcalaNetwork/chopsticks/tree/master/configs){target=\_blank}:
```bash
npx @acala-network/chopsticks@latest xcm \
--r=kusama.yml \
--p=moonriver.yml \
--p=karura.yml
```
You should see something like the following output:
```text
[13:50:57.807] INFO (rpc/64805): Loading config file https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/moonriver.yml
[13:50:59.655] INFO (rpc/64805): Moonriver RPC listening on port 8000
[13:50:59.656] INFO (rpc/64805): Loading config file https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/karura.yml
[13:51:03.275] INFO (rpc/64805): Karura RPC listening on port 8001
[13:51:03.586] INFO (xcm/64805): Connected parachains [2000,2023]
[13:51:03.586] INFO (rpc/64805): Loading config file https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/kusama.yml
[13:51:07.241] INFO (rpc/64805): Kusama RPC listening on port 8002
[13:51:07.700] INFO (xcm/64805): Connected relaychain 'Kusama' with parachain 'Moonriver'
[13:51:08.386] INFO (xcm/64805): Connected relaychain 'Kusama' with parachain 'Karura'
```
Including the `r` flag as the relay chain is optional, as Chopsticks will automatically mock a relay chain between networks. You can also use a raw GitHub URL or the name of a popular branch, similar to the base command.
## WebSocket Commands {: #websocket-commands }
Chopsticks' internal websocket server has special endpoints that allows the manipulation of the local Substrate chain. These are the methods that can be invoked:
| Method | Parameters | Description |
|:----------------:|:---------------------:|:-------------------------------------------------------------:|
| `dev_newBlock` | `options` | Generates one or more new blocks. |
| `dev_setStorage` | `values`, `blockHash` | Create or overwrite the value of any storage. |
| `dev_timeTravel` | `date` | Sets the timestamp of the block to the `date` value. |
| `dev_setHead` | `hashOrNumber` | Sets the head of the blockchain to a specific hash or number. |
The parameters above are formatted in the following ways:
| Parameter | Format | Example |
|:--------------:|:-----------------------------------:|:----------------------------------------------------------------------:|
| `options` | `{ "to": number, "count": number }` | `{ "count": 5 }` |
| `values` | `Object` | `{ "Sudo": { "Key": "0x6Be02d1d3665660d22FF9624b7BE0551ee1Ac91b" } }` |
| `blockHash` | `string` | `"0x1a34506b33e918a0106b100db027425a83681e2332fe311ee99d6156d2a91697"` |
| `date` | `Date` | `"2030-08-15T00:00:00"` |
| `hashOrNumber` | `number | string` |
- **`options` { "to": number, "count": number }** - a JSON object where `"to"` will create blocks up to a certain value, and `"count"` will increase by a certain number of blocks. Use only one entry at a time within the JSON object
- **`values` Object** - a JSON object resembling the path to a storage value, similar to what you would retrieve via Polkadot.js
- **`blockHash` string** - optional, the blockhash at which the storage value is changed
- **`date` Date** - a Date string (compatible with the JavaScript Date library) that will change the time stamp from which the next blocks being created will be at. All future blocks will be sequentially after that point in time
- **`hashOrNumber` number | string** - if found, the chain head will be set to the block with the block number or block hash of this value
Each method can be invoked by connecting to the websocket (`ws://localhost:8000` by default) and sending the data and parameters in the following format. Replace `METHOD_NAME` with the name of the method, and replace or delete `PARAMETER_1` and `PARAMETER_2` with the parameter data relevant to the method:
```json
{
"jsonrpc": "2.0",
"id": 1,
"method": "METHOD_NAME",
"params": ["PARAMETER_1", "PARAMETER_2", "..."]
}
```
The information presented herein has been provided by third parties and is made available solely for general information purposes. Moonbeam does not endorse any project listed and described on the Moonbeam Doc Website (https://docs.moonbeam.network/). Moonbeam Foundation does not warrant the accuracy, completeness or usefulness of this information. Any reliance you place on such information is strictly at your own risk. Moonbeam Foundation disclaims all liability and responsibility arising from any reliance placed on this information by you or by anyone who may be informed of any of its contents. All statements and/or opinions expressed in these materials are solely the responsibility of the person or entity providing those materials and do not necessarily represent the opinion of Moonbeam Foundation. The information should not be construed as professional or financial advice of any kind. Advice from a suitably qualified professional should always be sought in relation to any particular matter or circumstance. The information herein may link to or integrate with other websites operated or content provided by third parties, and such other websites may link to this website. Moonbeam Foundation has no control over any such other websites or their content and will have no liability arising out of or related to such websites or their content. The existence of any such link does not constitute an endorsement of such websites, the content of the websites, or the operators of the websites. These links are being provided to you only as a convenience and you release and hold Moonbeam Foundation harmless from any and all liability arising from your use of this information or the information provided by any third-party website or service.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/substrate/interfaces/account/identity/
--- BEGIN CONTENT ---
---
title: Identity Pallet
description: This guide covers the available functions in the Identity Pallet on Moonbeam, which are used to create and manage on-chain identities.
categories: Substrate Toolkit
---
# The Identity Pallet
## Introduction {: #introduction }
The [Substrate](/learn/platform/technology/#substrate-framework){target=\_blank} Identity Pallet is an out-of-the-box solution for adding personal information to your on-chain account. Personal information can include default fields such as your legal name, display name, website, Twitter handle, and Riot (now known as Element) name. You can also take advantage of custom fields to include any other relevant information.
The pallet also includes functionality to request judgments and verify on-chain identities from registrars, which are accounts appointed via governance to verify the identity information submitted and provide judgment on their findings for a fee.
This guide will provide an overview of the extrinsics, storage methods, and getters for the pallet constants available in the Identity Pallet on Moonbeam. This guide assumes you are familiar with identity-related terminology; if not, please check out the [Managing your Account Identity](/tokens/manage/identity/){target=\_blank} page for more information.
## Identity Pallet Interface {: #preimage-pallet-interface }
### Extrinsics {: #extrinsics }
The Identity Pallet provides the following extrinsics (functions):
??? function "**addRegistrar**(account) - adds an account as a registrar. Must be executed by the General Admin Origin"
=== "Parameters"
- `account` - the account to add as a registrar
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const account = INSERT_ACCOUNT;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.identity.addRegistrar(account);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**addSub**(sub, data) - adds an account as a sub-account of the caller. You can optionally provide a name for the sub-account. This function is not callable via a `NonTransfer` proxy. You can sign the transaction directly or use a different [proxy type](/tokens/manage/proxy-accounts/#proxy-types){target=\_blank} (`Any`, `IdentityJudgement`, etc.)"
=== "Parameters"
- `sub` - the account to add as a sub-account
- `data` - an object that specifies the name of the sub-account, where the key is the data type and the value is the data. You can use any of the following data types to define the name of the sub-account:
- `None` - no name should be used
- `Raw` - a raw value using hex or ascii
- `BlakeTwo256` - a BLAKE2-256 hash value
- `Sha256` - a SHA-256 value
- `Keccak256` - a Keccak-256 value
- `ShaThree256` - a SHA3-256 value
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const sub = 'INSERT_SUB_ACCOUNT';
const data = { INSERT_DATA_TYPE: 'INSERT_DATA' };
/*
For None, use the following format:
const data = { 'None': null };
For all other data types, use the name of the data type
and the value formatted in that specific type. For example:
const data = { 'Raw': 'Alice' };
*/
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.identity.addSub(sub, data);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**cancelRequest**(regIndex) - cancels the caller's request for judgment from a given registrar"
=== "Parameters"
- `regIndex` - the index of the registrar
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const regIndex = 'INSERT_INDEX_OF_REGISTRAR';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.identity.cancelRequest(regIndex);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**clearIdentity**() - clears the identity for the caller"
=== "Parameters"
None.
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.identity.clearIdentity();
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**killIdentity**(target) - removes an account's identity and sub-accounts. Must be executed by the General Admin Origin"
=== "Parameters"
- `target` - the account to remove the identity and sub-accounts for
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const target = 'INSERT_TARGET_ACCOUNT';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.identity.killIdentity(target);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**provideJudgement**(regIndex, target, judgement, identity) - provides judgment on an account's identity. The caller must be the registrar account that corresponds to the `index`. Must be executed by a registrar"
=== "Parameters"
- `regIndex` - the index of the registrar submitting the judgement
- `target` - the account to provide the judgment for
- `judgement` - the judgement or level of confidence in the identity information provided. There are seven levels of confidence, you can either provide the name or the index of the confidence level:
- `Unknown` or `0` - no judgement made yet. This is the default value
- `FeePaid` or `1` - indicates a user has requested judgement and it is in progress
- `Reasonable` or `2` - the information appears reasonable, but no in-depth checks were performed using legal identity documents
- `KnownGood` or `3` - the information is correct and is based upon review of legal identity documents
- `OutOfDate` or `4` - the information used to be good, but is now out of date
- `LowQuality` or `5` - the information is low quality or imprecise, but can be updated as needed
- `Erroneous` or `6` - the information is erroneous and may indicate malicious intent. This state cannot be modified and can only be removed if the entire identity has been removed
- `identity` - the 32-byte hash of the identity
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const regIndex = 'INSERT_REGISTRAR_INDEX';
const target = 'INSERT_TARGET_ACCOUNT';
const judgement = 'INSERT_JUDGEMENT';
const identity = 'INSERT_IDENTITY';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.identity.provideJudgement(
regIndex,
target,
judgement,
identity
);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**quitSub**() - removes the caller as a sub-identity account"
=== "Parameters"
None.
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.identity.quitSub();
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**removeSub**(sub) - removes a sub-identity account for the caller"
=== "Parameters"
- `sub` - the sub-identity account to remove
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const sub = 'INSERT_ACCOUNT';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.identity.removeSub(sub);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
```
??? function "**renameSub**(sub) - renames a sub-identity account for the caller"
=== "Parameters"
- `sub` - the sub-identity account to rename
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const sub = 'INSERT_ACCOUNT';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.identity.rename(sub);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
```
??? function "**requestJudgement**(regIndex, maxFee) - requests judgment from a given registrar along with the maximum fee the caller is willing to pay"
=== "Parameters"
- `regIndex` - the index of the registrar to request judgement from
- `maxFee` - the maximum fee in Wei that can be paid to the registrar for providing judgement
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const regIndex = INSERT_REGISTRAR_INDEX;
const maxFee = INSERT_MAX_FEE;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.identity.requestJudgement(regIndex, maxFee);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**setAccountId**(index, new) - sets a new account for an existing registrar. Must be executed by the registrar account that corresponds to the `index`."
=== "Parameters"
- `index` - the index of the registrar
- `new` - the account to set as the registrar's new account
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const index = INSERT_REGISTRAR_INDEX;
const newAccount = 'INSERT_NEW_ACCOUNT';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.identity.setAccountId(index, newAccount);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**setFee**(index, fee) - sets the fee for a registar. Must be executed by the registrar account that corresponds to the `index`"
=== "Parameters"
- `index` - the index of the registrar
- `fee` - the fee in Wei required to be paid to the registrar for a judgement
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const index = INSERT_REGISTRAR_INDEX;
const fee = INSERT_FEE;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.identity.setFee(index, fee);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**setFields**(index, fields) - sets the fields that a registrar cares about when providing judgements. Must be executed by the registrar account that corresponds to the `index`"
=== "Parameters"
- `index` - the index of the registrar
- `fields` - an array of the fields that the registrar cares about. The fields can be any of the following:
- `Display` - a display name
- `Legal` - a legal name
- `Web` - a website
- `Riot` - a Riot username
- `Email` - an email address
- `PpgFingerprint` - a PPG fingerprint
- `Image` - an image
- `Twitter` - a Twitter username
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const index = INSERT_REGISTRAR_INDEX;
const fields = [INSERT_FIELDS];
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.identity.setFields(index, fields);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**setIdentity**(info) - sets the identity for the caller"
=== "Parameters"
- `info` - the identity information. The identity information can include any of the following optional fields:
- `display` - a display name
- `legal` - a legal name
- `web` - a website
- `riot` - a Riot username
- `email` - an email address
- `ppgFingerprint` - a PPG fingerprint
- `image` - an image
- `twitter` - a Twitter username
- `additional` - an array that contains custom fields for additional information. Each additional item is represented as an array that contains two objects: one for the field name and one for the field value. You can define the additional field names and values in the following formats:
- `None` - no additional information should be used
- `Raw` - a raw value using hex or ascii
- `BlakeTwo256` - a BLAKE2-256 hash value
- `Sha256` - a SHA-256 value
- `Keccak256` - a Keccak-256 value
- `ShaThree256` - a SHA3-256 value
When setting an identity, a deposit is required. If setting additional fields, an additional deposit will be required per each additional field. For more information, please refer to the [Manage an Identity](/tokens/manage/identity#general-definitions){target=_blank} documentation.
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
/*
Add as many or as few fields as you would like
*/
const info = {
display: 'INSERT_DISPLAY_NAME',
legal: 'INSERT_LEGAL_NAME',
additional: [[{ Raw: 'Discord' }, { Raw: 'INSERT_DISCORD_USERNAME' }]],
};
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.identity.setIdentity(info);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**setSubs**(subs) - sets the sub-accounts for the caller. This function is not callable via a `NonTransfer` proxy. You can sign the transaction directly or use a different [proxy type](/tokens/manage/proxy-accounts/#proxy-types){target=\_blank} (`Any`, `IdentityJudgement`, etc.)"
=== "Parameters"
- `subs` - an array that defines the sub-accounts. Each sub-account is represented as an array itself, with the address of the sub-account as the zero index and the name as the first index. The name is an object that can be defined in the following formats:
- `None` - no additional information should be used
- `Raw` - a raw value using hex or ascii
- `BlakeTwo256` - a BLAKE2-256 hash value
- `Sha256` - a SHA-256 value
- `Keccak256` - a Keccak-256 value
- `ShaThree256` - a SHA3-256 value
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const subs = [
[INSERT_ACCOUNT, { Raw: 'INSERT_SUB_ACCOUNT_NAME' }],
[INSERT_ACCOUNT, { None: null }],
];
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.identity.setSubs(subs);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
### Storage Methods {: #storage-methods }
The Identity Pallet includes the following read-only storage methods to obtain chain state data:
??? function "**authorityOf**(account) – returns authority properties for a given account"
=== "Parameters"
- `account` – the 20-byte account ID (`AccountId20`) you want to inspect.
=== "Returns"
An `Option`
If the supplied account **is not** a username-granting authority, the call returns `null`.
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Connect to Moonbase
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-rpc.dwellir.com'),
});
// --- OPTION 1: Check a single account ----------------------
// const account = '0x1234...'; // AccountId20 as hex
// const infoOpt = await api.query.identity.authorityOf(account);
// console.log(infoOpt.isSome ? infoOpt.unwrap().toHuman() : 'Not an authority');
// --- OPTION 2: List *all* registered authorities -----------
const entries = await api.query.identity.authorityOf.entries();
if (entries.length === 0) {
console.log('No authority accounts are registered.');
} else {
console.log(`Found ${entries.length} authority account(s):\n`);
for (const [storageKey, optProps] of entries) {
if (optProps.isSome) {
const account = storageKey.args[0].toString();
const { allowAutoClaim, deposit, provider } = optProps.unwrap();
console.log(`• ${account}`);
console.log(` allowAutoClaim : ${allowAutoClaim.toString()}`);
console.log(` deposit : ${deposit.toString()}`);
console.log(` provider : ${provider.toString()}\n`);
}
}
}
await api.disconnect();
};
main().catch(console.error);
```
??? function "**identityOf**(account) - returns identity information for a given account"
=== "Parameters"
- `account` - the account to get identity information for
=== "Returns"
Identity information for the given account, including judgments (if the account has requested a judgment from a registrar), the deposit is held for the identity and the identity information. If the account does not have an identity set, `null` is returned.
```js
// If using Polkadot.js API and calling toJSON() on the query results
{
judgements: [],
deposit: '0x00000000000000000e53d254821d0000',
info: {
additional: [ [Array] ],
display: { raw: '0x416c697468' },
legal: { none: null },
web: { none: null },
riot: { none: null },
email: { raw: '0x616c69746840616c6974682e636f6d' },
pgpFingerprint: null,
image: { none: null },
twitter: { none: null }
}
}
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
// Helper function to decode hex to string
const hexToString = (hex) => {
// Remove '0x' prefix if present
const cleanHex = hex.startsWith('0x') ? hex.slice(2) : hex;
// Convert hex to string
const str = Buffer.from(cleanHex, 'hex').toString('utf8');
return str;
};
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
const account = 'INSERT_ACCOUNT';
const identity = await api.query.identity.identityOf(account);
console.log('Raw identity response:', identity.toString());
if (identity) {
// Parse the raw response
const rawResponse = JSON.parse(identity.toString());
if (rawResponse[0]) {
const formattedIdentity = {
judgements: rawResponse[0].judgements,
deposit: rawResponse[0].deposit,
info: {
additional: rawResponse[0].info.additional,
display: rawResponse[0].info.display.raw
? hexToString(rawResponse[0].info.display.raw)
: null,
legal: rawResponse[0].info.legal,
web: rawResponse[0].info.web,
riot: rawResponse[0].info.riot,
email: rawResponse[0].info.email,
pgpFingerprint: rawResponse[0].info.pgpFingerprint,
image: rawResponse[0].info.image,
twitter: rawResponse[0].info.twitter,
},
};
console.log(
'Formatted Identity:',
JSON.stringify(formattedIdentity, null, 2)
);
} else {
console.log('No identity data found in the response');
}
} else {
console.log('No identity found for this account');
}
} catch (error) {
console.error('Error querying identity:', error);
} finally {
await api.disconnect();
}
};
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**palletVersion**() - returns the current pallet version"
=== "Parameters"
None
=== "Returns"
The version of the pallet, e.g. `1`
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Create the API instance
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Query the identity pallet version
const version = await api.query.identity.palletVersion();
// Log the version to console
console.log('Identity Pallet Version:', version.toString());
// Disconnect from the API
await api.disconnect();
};
main().catch(console.error);
```
??? function "**pendingUsernames**(username) - returns information for a pending username"
=== "Parameters"
- `username` – the username to query.
Pass it as a `Bytes` value (hex-encoded or plain ASCII).
=== "Returns"
An `Option` that is:
- `null` – if the username is **not** pending, or
- `(AccountId20, u32, PalletIdentityProvider)` – when pending, where
- `AccountId20` is the account that has been offered the username
- `u32` is the **block number deadline** by which the account must accept it
- `PalletIdentityProvider` is the authority that issued the username
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Connect to a Moonbase RPC endpoint
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-rpc.dwellir.com'),
});
// Fetch *all* [StorageKey, Option<(AccountId20, u32, PalletIdentityProvider)>] pairs
const entries = await api.query.identity.pendingUsernames.entries();
if (entries.length === 0) {
console.log('There are no pending usernames right now.');
} else {
console.log(`Found ${entries.length} pending username(s):\n`);
for (const [storageKey, optValue] of entries) {
if (optValue.isSome) {
const [account, deadline, provider] = optValue.unwrap();
// The username itself is part of the storage key after the 32-byte hash prefix
// api.registry.createType('Bytes', rawBytes) makes it human-readable
const raw = storageKey.args[0]; // Bytes
const username = api.registry.createType('Bytes', raw).toUtf8();
console.log(`• ${username}`);
console.log(` owner : ${account.toString()}`);
console.log(` expires : block ${deadline.toNumber()}`);
console.log(` provider: ${provider.toString()}\n`);
}
}
}
await api.disconnect();
};
main().catch(console.error);
```
??? function "**registrars**() - returns the set of registrars"
=== "Parameters"
None
=== "Returns"
The set of registrators as a vector
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Create the API instance
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Query the registrars
const registrars = await api.query.identity.registrars();
// Format and log the registrars data
const formattedRegistrars = registrars
.map((reg) => {
if (!reg.isSome) return null;
const { account, fee, fields } = reg.unwrap();
return {
account: account.toString(),
fee: fee.toHuman(),
fields: fields.toNumber(),
};
})
.filter((reg) => reg !== null);
console.log('Registrars:', JSON.stringify(formattedRegistrars, null, 2));
// Disconnect from the API
await api.disconnect();
};
main().catch(console.error);
```
??? function "**subsOf**(AccountId20) - returns the sub-identities for all accounts or a given account"
=== "Parameters"
- `AccountId20` the account to check the sub-identities for
=== "Returns"
The sub-identities, if any.
```
Raw subs response: [0,[]]
Formatted Subs: {
"deposit": "0",
"subAccounts": []
}
Number of sub-accounts: 0
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
const account = 'INSERT_ACCOUNT';
const subs = await api.query.identity.subsOf(account);
// Log raw response for debugging
console.log('Raw subs response:', subs.toString());
if (subs) {
// The response includes a tuple of [deposit, accounts]
const [deposit, subAccounts] = subs;
const formattedSubs = {
deposit: deposit.toHuman(),
subAccounts: subAccounts.toHuman(),
};
console.log('Formatted Subs:', JSON.stringify(formattedSubs, null, 2));
console.log('Number of sub accounts:', subAccounts.length);
} else {
console.log('No sub identities found for this account');
}
} catch (error) {
console.error('Error querying sub identities:', error);
} finally {
await api.disconnect();
}
};
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**superOf**(AccountId20) - returns the super identity of all sub-accounts or for a given sub-account"
=== "Parameters"
- `AccountId20` - the account to check the super identities of
=== "Returns"
The super identities, if any.
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
const account = 'INSERT_ACCOUNT';
const superOf = await api.query.identity.superOf(account);
// Log raw response for debugging
console.log('Raw superOf response:', superOf.toString());
if (superOf.isSome) {
// The response includes a tuple of [parentAccount, dataName]
const [parentAccount, dataName] = superOf.unwrap();
const formattedSuper = {
parentAccount: parentAccount.toString(),
dataName: dataName.toHuman(),
};
console.log(
'Formatted Super Identity:',
JSON.stringify(formattedSuper, null, 2)
);
} else {
console.log('This account is not a sub-identity of any other account');
}
} catch (error) {
console.error('Error querying super identity:', error);
} finally {
await api.disconnect();
}
};
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**unbindingUsernames**(username) – returns the block height at which a username being revoked will be released"
=== "Parameters"
- `username` – the username to inspect, supplied as `Bytes` (plain ASCII or hex).
=== "Returns"
An `Option`: it is `null` when the username is **not** in the unbinding process; otherwise it contains the block number after which the username becomes free to claim again.
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Connect to Moonbase
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-rpc.dwellir.com'),
});
// Fetch every (StorageKey, Option) pair
const entries = await api.query.identity.unbindingUsernames.entries();
if (entries.length === 0) {
console.log('There are no usernames in the unbinding process.');
} else {
console.log(`Found ${entries.length} unbinding username(s):\n`);
for (const [storageKey, optBlock] of entries) {
if (optBlock.isSome) {
// The username itself is the single argument encoded in the storage key
const rawUsername = storageKey.args[0];
const username = api.registry.createType('Bytes', rawUsername).toUtf8();
const releaseBlock = optBlock.unwrap().toNumber();
console.log(`${username} → releases at block ${releaseBlock}`);
}
}
}
await api.disconnect();
};
main().catch(console.error);
```
??? function "**usernameInfoOf**(username) – returns information for a given username"
=== "Parameters"
- `username` – the username to look up.
Supply it as a `Bytes` value (plain ASCII or hex).
=== "Returns"
An `AccountId20` of the Account currently bound to the username and a provider value, i.e., the authority that issued the username.
If the username is **unregistered**, the call returns `null`.
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Connect to Moonbase-Alpha
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-rpc.dwellir.com'),
});
// Username to query (ASCII automatically wrapped as Bytes)
const username = api.registry.createType('Bytes', 'alice');
// Fetch username information
const infoOpt = await api.query.identity.usernameInfoOf(username);
if (infoOpt.isSome) {
const { owner, provider } = infoOpt.unwrap();
console.log(`Username : ${username.toUtf8()}`);
console.log(` Owner account : ${owner.toString()}`);
console.log(` Issued by : ${provider.toString()}`);
} else {
console.log('Username is not registered.');
}
await api.disconnect();
};
main().catch(console.error);
```
??? function "**usernameOf**(account) – returns the primary username bound to an account"
=== "Parameters"
- `account` – the `AccountId20` you want to query.
=== "Returns"
Returns an `Option`: it is null when the account has no primary username; otherwise, it contains a Bytes value with the UTF-8 (or hex-encoded) string of the account’s primary username.
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Connect to Moonbase
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-rpc.dwellir.com'),
});
// Replace with any AccountId20 you wish to inspect
const account = 'INSERT_ACCOUNT';
// Query the storage item
const usernameOpt = await api.query.identity.usernameOf(account);
if (usernameOpt.isSome) {
// Convert Bytes → UTF-8 for readability
const username = usernameOpt.unwrap().toUtf8();
console.log(`Primary username for ${account}: ${username}`);
} else {
console.log(`Account ${account} has no primary username set.`);
}
await api.disconnect();
};
main().catch(console.error);
```
### Pallet Constants {: #constants }
The Identity Pallet includes the following read-only functions to obtain pallet constants:
??? function "**basicDeposit**() - returns the amount held on deposit for a registered identity"
=== "Parameters"
None
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Query the basicDeposit constant
const basicDeposit = api.consts.identity.basicDeposit;
// Log raw response for debugging
console.log('Raw basicDeposit response:', basicDeposit.toString());
// Format the deposit amount
console.log('Basic Deposit (formatted):', basicDeposit.toHuman());
} catch (error) {
console.error('Error querying basic deposit:', error);
} finally {
await api.disconnect();
}
};
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
=== "Example Response"
```bash
Raw basicDeposit response: 1025800000000000000
Basic Deposit (formatted): 1,025,800,000,000,000,000
```
??? function "**byteDeposit**() - returns the amount held on deposit per additional bytes of data for a registered identity"
=== "Parameters"
None
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Query the byteDeposit constant
const byteDeposit = api.consts.identity.byteDeposit;
// Log raw response for debugging
console.log('Raw byteDeposit response:', byteDeposit.toString());
// Format the deposit amount
console.log('Byte Deposit (formatted):', byteDeposit.toHuman());
} catch (error) {
console.error('Error querying byte deposit:', error);
} finally {
await api.disconnect();
}
};
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
=== "Example Response"
```
Raw byteDeposit response: 100000000000000
Byte Deposit (formatted): 100,000,000,000,000
```
??? function "**maxRegistrars**() - returns the maximum number of registrars allowed in the system"
=== "Parameters"
None
=== "Returns"
- `u32` - Maximum number of registrars allowed
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Query the maxRegistrars constant
const maxRegistrars = api.consts.identity.maxRegistrars;
// Get the number as a plain integer
console.log('Max Registrars (number):', maxRegistrars.toNumber());
} catch (error) {
console.error('Error querying max registrars:', error);
} finally {
await api.disconnect();
}
};
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**maxSubAccounts**() - returns the maximum number of sub-accounts allowed per account"
=== "Parameters"
None
=== "Returns"
- `u32` - Maximum number of sub-accounts allowed per identity
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
const maxSubAccounts = api.consts.identity.maxSubAccounts;
console.log('Max SubAccounts (number):', maxSubAccounts.toNumber());
} catch (error) {
console.error('Error querying max subaccounts:', error);
} finally {
await api.disconnect();
}
};
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**subAccountDeposit**() - returns the amount held on deposit for a registered sub-account"
=== "Parameters"
None
=== "Returns"
- `Balance` - Amount of currency held on deposit for a sub-account
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
const subAccountDeposit = api.consts.identity.subAccountDeposit;
console.log('SubAccount Deposit:', subAccountDeposit.toHuman());
} catch (error) {
console.error('Error querying subaccount deposit:', error);
} finally {
await api.disconnect();
}
};
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**pendingUsernameExpiration**() - returns the time period for which a username remains pending"
=== "Parameters"
None
=== "Returns"
- `BlockNumber` - Number of blocks before a pending username expires
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Query the pendingUsernameExpiration constant from identity pallet
const pendingExpiration = api.consts.identity.pendingUsernameExpiration;
console.log('Pending Username Expiration:', pendingExpiration.toHuman());
} catch (error) {
console.error('Error querying pending username expiration:', error);
} finally {
await api.disconnect();
}
};
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**maxSuffixLength**() - returns the maximum length allowed for a username suffix"
=== "Parameters"
None
=== "Returns"
- `u32` - Maximum number of characters allowed in a username suffix
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
const maxSuffixLength = api.consts.identity.maxSuffixLength;
console.log('Max Suffix Length:', maxSuffixLength.toHuman());
} catch (error) {
console.error('Error querying max suffix length:', error);
} finally {
await api.disconnect();
}
};
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**maxUsernameLength**() - returns the maximum length allowed for a username"
=== "Parameters"
None
=== "Returns"
- `u32` - Maximum number of characters allowed in a username
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
const maxUsernameLength = api.consts.identity.maxUsernameLength;
console.log('Max Username Length:', maxUsernameLength.toHuman());
} catch (error) {
console.error('Error querying max username length:', error);
} finally {
await api.disconnect();
}
};
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/substrate/interfaces/account/multisig/
--- BEGIN CONTENT ---
---
title: Multisig Pallet
description: Learn about the Multisig Pallet, which taps into Substrate functionality to provide the ability to approve and dispatch calls from a multisig on Moonbeam.
categories: Substrate Toolkit
---
# The Multisig Pallet
## Introduction {: #introduction }
Multisig wallets are a special type of wallet that requires multiple signatures in order to execute transactions, as the name implies. A multisig has a set of signers and defines a threshold for the number of signatures required to approve a transaction. This type of wallet provides an additional layer of security and decentralization.
The Multisig Pallet on Moonbeam taps into Substrate functionality to allow for the ability to natively approve and dispatch calls from a multisig. With the Multisig Pallet, multiple signers, also referred to as signatories in Substrate, approve and dispatch transactions from an origin that is derivable deterministically from the set of signers' account IDs and the threshold for the number of accounts from the set that must approve calls before they can be dispatched.
This page will provide an overview of the extrinsics, storage methods, and getters for the pallet constants available in the Multisig Pallet on Moonbeam. It will also include a brief demo on how to create a multisig account and send a transaction that requires two of three signers to approve and dispatch the transaction.
## Multisig Pallet Interface {: #multisig-pallet-interface }
### Extrinsics {: #extrinsics }
The Multisig Pallet provides the following extrinsics (functions):
??? function "**asMulti**(threshold, otherSignatories, maybeTimepoint, call, maxWeight) - approves and if possible dispatches a call from a composite origin formed from a number of signed origins (a multisig). If the call has been approved by enough of the other signatories, the call will be dispatched. The [`depositBase`](#constants) will be reserved if this is the first approval plus the `threshold` times the [`depositFactor`](#constants). The total reserved amount will be returned once the call is dispatched or cancelled. This function should be used if it is the final approval, otherwise you'll want to use `approveAsMulti` instead since it only requires a hash of the call"
=== "Parameters"
- `threshold` - The total number of approvals required for the dispatch to be executed
- `otherSignatories` - The accounts (other than the sender) who can approve the dispatch
- `maybeTimepoint` - The timepoint (block number and transaction index) of the first approval transaction. Must be `None` if this is the first approval
- `call` - The actual call to be executed once approved
- `maxWeight` - The maximum weight allowed for the dispatch
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
import { bnToHex, stringToHex } from '@polkadot/util';
const main = async () => {
// Initialize API connection
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
const keyring = new Keyring({ type: 'ethereum' });
try {
// Configuration
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const MULTISIG_ADDRESS = 'INSERT_ADDRESS_MULTISIG';
// Multisig parameters
const threshold = 2;
const otherSignatories = ['INSERT_SIGNER_1', 'INSERT_SIGNER_2'].sort(); // Addresses must be sorted
// Create an EVM transaction
const TARGET_ADDRESS = 'INSERT_DESTINATION_ADDRESS';
const VALUE = '1000000000000000000'; // 1 TOKEN in Wei
// Construct the EVM call data
const call = api.tx.evm.call(
MULTISIG_ADDRESS, // source address
TARGET_ADDRESS, // target address
VALUE, // value in Wei
'0x', // input data (empty for simple transfer)
'2100000', // gas limit
'1000000000', // max fee per gas (1 GWei)
'1000000000', // max priority fee per gas (1 GWei)
null, // nonce (optional)
[] // access list (optional)
);
// Weight limits for the dispatch
const maxWeight = {
refTime: '806342022',
proofSize: '211174',
};
const account = keyring.addFromUri(PRIVATE_KEY);
// Check for existing timepoint
const callHash = call.method.hash.toHex();
const multisigs = await api.query.multisig.multisigs(
MULTISIG_ADDRESS,
callHash
);
let maybeTimepoint = null;
if (multisigs.isSome) {
const multisigInfo = multisigs.unwrap();
maybeTimepoint = {
height: multisigInfo.when.height.toNumber(),
index: multisigInfo.when.index.toNumber(),
};
}
console.log('Validation checks:');
console.log('Account address:', account.address);
console.log('Multisig address:', MULTISIG_ADDRESS);
console.log('Other signatories:', otherSignatories);
console.log('Threshold:', threshold);
console.log('Call hash:', callHash);
console.log('Max weight:', maxWeight);
console.log('Timepoint:', maybeTimepoint);
// Create and send the asMulti transaction
const tx = api.tx.multisig.asMulti(
threshold,
otherSignatories,
maybeTimepoint,
call,
maxWeight
);
// Sign and send the transaction
await tx.signAndSend(account, ({ status, events }) => {
if (status.isInBlock) {
console.log(`Transaction included in block hash: ${status.asInBlock}`);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
});
// Check for specific multisig events
const multisigEvent = events.find(
({ event }) =>
event.section === 'multisig' &&
(event.method === 'MultisigExecuted' ||
event.method === 'NewMultisig')
);
if (multisigEvent) {
console.log('Multisig event:', multisigEvent.event.method);
}
process.exit(0);
}
});
} catch (error) {
console.error('Error in multisig execution:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
=== "Example Response"
```
Validation checks:
Account address: 0x3B939FeaD1557C741Ff06492FD0127bd287A421e
Multisig address: 0x2c6a9d09E7C01f3D4154000193BDDcC597523221
Other signatories: [
'0x253b05C595222a1e3E7Bcf1611cA1307194a030F',
'0x4B718e1CCeb83bfE87FD5f79cb98FFc2d4600C7E'
]
Threshold: 2
Call hash: 0xdbbc67f35ca518976f4d392fb32745786e6b58fc526fab0dafb6eda44d9850a3
Max weight: { refTime: '806342022', proofSize: '211174' }
Timepoint: null
Transaction included in block hash: 0x0050f1b137e5814dc4eb16390d10287d9234de1d5827dd64ba85c878d4c53849
balances.Withdraw: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",4858229333763]
balances.Reserved: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e","0x00000000000000000e1107d468560000"]
multisig.NewMultisig: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e","0x2c6a9d09E7C01f3D4154000193BDDcC597523221","0xdbbc67f35ca518976f4d392fb32745786e6b58fc526fab0dafb6eda44d9850a3"]
balances.Deposit: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",1222550823750]
balances.Deposit: ["0x6d6F646c70632f74727372790000000000000000",727135702003]
transactionPayment.TransactionFeePaid: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",3635678510013,0]
system.ExtrinsicSuccess: [{"weight":{"refTime":404917324,"proofSize":5587},"class":"Normal","paysFee":"Yes"}]
Multisig event: NewMultisig
```
??? function "**approveAsMulti**(threshold, otherSignatories, maybeTimepoint, callHash, maxWeight) - approves a call from a composite origin. For the final approval, you'll want to use `asMulti` instead"
=== "Parameters"
- `threshold` - The total number of approvals required for the dispatch to be executed
- `otherSignatories` - The accounts (other than the sender) who can approve the dispatch
- `maybeTimepoint` - The timepoint (block number and transaction index) of the first approval transaction. Must be `None` if this is the first approval
- `callHash` - The hash of the call to be executed
- `maxWeight` - The maximum weight allowed for the dispatch
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
const keyring = new Keyring({ type: 'ethereum' });
try {
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const threshold = 2;
const otherSignatories = ['INSERT_SIGNER_1', 'INSERT_SIGNER_2'].sort();
const callHash = 'INSERT_CALL_HASH';
const maxWeight = {
refTime: '806342022',
proofSize: '211174',
};
// Query the multisig address instead of the signer's address
const MULTISIG_ADDRESS = 'INSERT_ADDRESS_MULTISIG';
const multisigs = await api.query.multisig.multisigs(
MULTISIG_ADDRESS,
callHash
);
if (!multisigs.isSome) {
console.error('No existing multisig found for this call hash');
process.exit(1);
}
const multisigInfo = multisigs.unwrap();
const timepoint = {
height: multisigInfo.when.height.toNumber(),
index: multisigInfo.when.index.toNumber(),
};
const account = keyring.addFromUri(PRIVATE_KEY);
console.log('Found timepoint:', timepoint);
console.log('Validation checks:');
console.log('Account address:', account.address);
console.log('Multisig address:', MULTISIG_ADDRESS);
console.log('Other signatories:', otherSignatories);
console.log('Threshold:', threshold);
console.log('Call hash:', callHash);
console.log('Max weight:', maxWeight);
console.log('Timepoint:', timepoint);
const tx = api.tx.multisig.approveAsMulti(
threshold,
otherSignatories,
timepoint,
callHash,
maxWeight
);
await tx.signAndSend(account, ({ status, events }) => {
if (status.isInBlock) {
console.log(`Transaction included in block hash: ${status.asInBlock}`);
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
});
process.exit(0);
}
});
} catch (error) {
console.error('Error in multisig approval:', error);
process.exit(1);
}
};
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
=== "Example Response"
```bash
Found timepoint: { height: 9174086, index: 5 }
Validation checks:
Account address: 0x3B939FeaD1557C741Ff06492FD0127bd287A421e
Multisig address: 0x2c6a9d09E7C01f3D4154000193BDDcC597523221
Other signatories: [
'0x253b05C595222a1e3E7Bcf1611cA1307194a030F',
'0x4B718e1CCeb83bfE87FD5f79cb98FFc2d4600C7E'
]
Threshold: 2
Call hash: 0xa2902805948bdd92fcaf661965215efd6a5980d0092c065e7470859c1b37b6a9
Max weight: { refTime: '806342022', proofSize: '211174' }
Timepoint: { height: 9174086, index: 5 }
Transaction included in block hash: 0xb7b0f712dc7aa3d471e1db89e0d182b59e1febf8bb1df73a03f36417fe19b506
balances.Withdraw: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",4512391685922]
multisig.MultisigApproval: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",{"height":9174086,"index":5},"0x2c6a9d09E7C01f3D4154000193BDDcC597523221","0xa2902805948bdd92fcaf661965215efd6a5980d0092c065e7470859c1b37b6a9"]
balances.Deposit: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",1025179732500]
balances.Deposit: ["0x6d6F646c70632f74727372790000000000000000",697442390685]
transactionPayment.TransactionFeePaid: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",3487211953422,0]
system.ExtrinsicSuccess: [{"weight":{"refTime":389364247,"proofSize":5587},"class":"Normal","paysFee":"Yes"}]
```
??? function "**asMultiThreshold**(otherSignatories, call) - immediately dispatches a multisig call using a single approval from the caller"
=== "Parameters"
- `otherSignatories` - The accounts (other than the sender) who can approve the dispatch
- `call` - The actual call to be executed once approved
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
const keyring = new Keyring({ type: 'ethereum' });
try {
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const threshold = 2;
const otherSignatories = ['INSERT_SIGNER_1', 'INSERT_SIGNER_2'].sort();
const callHash = 'INSERT_CALL_HASH';
const maxWeight = {
refTime: '806342022',
proofSize: '211174',
};
const MULTISIG_ADDRESS = 'INSERT_ADDRESS_MULTISIG';
const multisigs = await api.query.multisig.multisigs(
MULTISIG_ADDRESS,
callHash
);
if (!multisigs.isSome) {
console.error('No existing multisig found for this call hash');
process.exit(1);
}
const multisigInfo = multisigs.unwrap();
const timepoint = {
height: multisigInfo.when.height.toNumber(),
index: multisigInfo.when.index.toNumber(),
};
const account = keyring.addFromUri(PRIVATE_KEY);
console.log('Found timepoint:', timepoint);
console.log('Validation checks:');
console.log('Account address:', account.address);
console.log('Multisig address:', MULTISIG_ADDRESS);
console.log('Other signatories:', otherSignatories);
console.log('Threshold:', threshold);
console.log('Call hash:', callHash);
console.log('Max weight:', maxWeight);
console.log('Timepoint:', timepoint);
const tx = api.tx.multisig.approveAsMulti(
threshold,
otherSignatories,
timepoint,
callHash,
maxWeight
);
await tx.signAndSend(account, ({ status, events }) => {
if (status.isInBlock) {
console.log(`Transaction included in block hash: ${status.asInBlock}`);
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
});
process.exit(0);
}
});
} catch (error) {
console.error('Error in multisig approval:', error);
process.exit(1);
}
};
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
=== "Example Response"
```
Found timepoint: { height: 9174086, index: 5 }
Validation checks:
Account address: 0x3B939FeaD1557C741Ff06492FD0127bd287A421e
Multisig address: 0x2c6a9d09E7C01f3D4154000193BDDcC597523221
Other signatories: [
'0x253b05C595222a1e3E7Bcf1611cA1307194a030F',
'0x4B718e1CCeb83bfE87FD5f79cb98FFc2d4600C7E'
]
Threshold: 2
Call hash: 0xa2902805948bdd92fcaf661965215efd6a5980d0092c065e7470859c1b37b6a9
Max weight: { refTime: '806342022', proofSize: '211174' }
Timepoint: { height: 9174086, index: 5 }
Transaction included in block hash: 0xb7b0f712dc7aa3d471e1db89e0d182b59e1febf8bb1df73a03f36417fe19b506
balances.Withdraw: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",4512391685922]
multisig.MultisigApproval: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",{"height":9174086,"index":5},"0x2c6a9d09E7C01f3D4154000193BDDcC597523221","0xa2902805948bdd92fcaf661965215efd6a5980d0092c065e7470859c1b37b6a9"]
balances.Deposit: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",1025179732500]
balances.Deposit: ["0x6d6F646c70632f74727372790000000000000000",697442390685]
transactionPayment.TransactionFeePaid: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",3487211953422,0]
system.ExtrinsicSuccess: [{"weight":{"refTime":389364247,"proofSize":5587},"class":"Normal","paysFee":"Yes"}]
```
??? function "**cancelAsMulti**(threshold, otherSignatories, maybeTimepoint, callHash) - cancels a preexisting, ongoing call from a composite origin. Any reserved deposit will be returned upon successful cancellation"
=== "Parameters"
- `threshold` - The total number of approvals required for the dispatch to be executed
- `otherSignatories` - The accounts (other than the sender) who can approve the dispatch
- `maybeTimepoint` - The timepoint (block number and transaction index) of the first approval transaction. Must be `None` if this is the first approval
- `callHash` - The hash of the call to be executed
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
const keyring = new Keyring({ type: 'ethereum' });
try {
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const threshold = 2;
const otherSignatories = ['INSERT_SIGNER_1', 'INSERT_SIGNER_2'].sort();
const callHash = 'INSERT_CALL_HASH';
// Query the multisig address for the timepoint
const MULTISIG_ADDRESS = 'INSERT_ADDRESS_MULTISIG';
const multisigs = await api.query.multisig.multisigs(
MULTISIG_ADDRESS,
callHash
);
if (!multisigs.isSome) {
console.error('No existing multisig found for this call hash');
process.exit(1);
}
const multisigInfo = multisigs.unwrap();
const timepoint = {
height: multisigInfo.when.height.toNumber(),
index: multisigInfo.when.index.toNumber(),
};
const account = keyring.addFromUri(PRIVATE_KEY);
console.log('Found timepoint:', timepoint);
console.log('Validation checks:');
console.log('Account address:', account.address);
console.log('Multisig address:', MULTISIG_ADDRESS);
console.log('Other signatories:', otherSignatories);
console.log('Threshold:', threshold);
console.log('Call hash:', callHash);
console.log('Timepoint:', timepoint);
const tx = api.tx.multisig.cancelAsMulti(
threshold,
otherSignatories,
timepoint,
callHash
);
await tx.signAndSend(account, ({ status, events }) => {
if (status.isInBlock) {
console.log(`Transaction included in block hash: ${status.asInBlock}`);
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
});
process.exit(0);
}
});
} catch (error) {
console.error('Error in multisig cancellation:', error);
process.exit(1);
}
};
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
=== "Example Response"
```bash
Found timepoint: { height: 9174086, index: 5 }
Validation checks:
Account address: 0x3B939FeaD1557C741Ff06492FD0127bd287A421e
Multisig address: 0x2c6a9d09E7C01f3D4154000193BDDcC597523221
Other signatories: [
'0x253b05C595222a1e3E7Bcf1611cA1307194a030F',
'0x4B718e1CCeb83bfE87FD5f79cb98FFc2d4600C7E'
]
Threshold: 2
Call hash: 0xa2902805948bdd92fcaf661965215efd6a5980d0092c065e7470859c1b37b6a9
Max weight: { refTime: '806342022', proofSize: '211174' }
Timepoint: { height: 9174086, index: 5 }
Transaction included in block hash: 0xb7b0f712dc7aa3d471e1db89e0d182b59e1febf8bb1df73a03f36417fe19b506
balances.Withdraw: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",4512391685922]
multisig.MultisigApproval: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",{"height":9174086,"index":5},"0x2c6a9d09E7C01f3D4154000193BDDcC597523221","0xa2902805948bdd92fcaf661965215efd6a5980d0092c065e7470859c1b37b6a9"]
balances.Deposit: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",1025179732500]
balances.Deposit: ["0x6d6F646c70632f74727372790000000000000000",697442390685]
transactionPayment.TransactionFeePaid: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",3487211953422,0]
system.ExtrinsicSuccess: [{"weight":{"refTime":389364247,"proofSize":5587},"class":"Normal","paysFee":"Yes"}]
```
### Storage Methods {: #storage-methods }
The Multisig Pallet includes the following read-only storage methods to obtain chain state data:
??? function "**multisigs**() - returns the set of open multisig operations for a given account."
=== "Parameters"
- `account` - The address of the multisig
- `callHash` - (Optional) The hash of the multisig call
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// The account to query multisigs for
const account = 'INSERT_ACCOUNT';
// Get all storage keys and values for this account's multisigs
const entries = await api.query.multisig.multisigs.entries(account);
if (entries.length === 0) {
console.log('No multisigs found for this account');
} else {
console.log(`Found ${entries.length} multisig(s):`);
entries.forEach(([key, value]) => {
// The key contains the call hash in its final 32 bytes
const callHash = key.args[1].toHex();
console.log('\nCall Hash:', callHash);
console.log('Details:', value.unwrap().toHuman());
});
}
} catch (error) {
console.error('Error querying multisigs:', error);
} finally {
await api.disconnect();
}
};
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
=== "Example Response"
```
[
[
[
0x2c6a9d09E7C01f3D4154000193BDDcC597523221
0xa2902805948bdd92fcaf661965215efd6a5980d0092c065e7470859c1b37b6a9
]
{
when: {
height: 9,174,086
index: 5
}
deposit: 1,013,600,000,000,000,000
depositor: 0x253b05C595222a1e3E7Bcf1611cA1307194a030F
approvals: [
0x253b05C595222a1e3E7Bcf1611cA1307194a030F
]
}
]
]
```
??? function "**palletVersion**() - returns the current pallet version"
=== "Parameters"
None
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Create the API instance
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Query the identity pallet version
const version = await api.query.multisig.palletVersion();
// Log the version to console
console.log('Identity Pallet Version:', version.toString());
// Disconnect from the API
await api.disconnect();
};
main().catch(console.error);
```
=== "Example Response"
`1`
### Pallet Constants {: #constants }
The Multisig Pallet includes the following read-only functions to obtain pallet constants:
??? function "**depositBase**() - returns the base amount of currency needed to reserve for creating a multisig execution or to store a dispatch call for later. This is held for an additional storage item whose key size is `32 + sizeof(AccountId)` bytes, which is `32 + 20` on Moonbeam, and whose value size is `4 + sizeof((BlockNumber, Balance, AccountId))` bytes, which is `4 + 4 + 16 +20` bytes on Moonbeam"
=== "Parameters"
None
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
const depositBase = api.consts.multisig.depositBase;
console.log('Multisig Deposit Base:', depositBase.toHuman());
} catch (error) {
console.error('Error querying deposit base:', error);
} finally {
await api.disconnect();
}
};
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
=== "Example Response"
```
Multisig Deposit Base: 1,009,600,000,000,000,000
```
??? function "**depositFactor**() - returns the amount of currency needed per unit threshold when creating a multisig execution. This is held for adding 20 bytes more into a preexisting storage value"
=== "Parameters"
None
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
const depositFactor = api.consts.multisig.depositFactor;
console.log('Multisig Deposit Factor:', depositFactor.toHuman());
} catch (error) {
console.error('Error querying deposit factor:', error);
} finally {
await api.disconnect();
}
};
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
=== "Example Response"
```
Multisig Deposit Factor: 2,000,000,000,000,000
```
??? function "**maxSignatories**() - returns the maximum amount of signatories allowed in the multisig"
=== "Parameters"
None
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
const maxSignatories = api.consts.multisig.maxSignatories;
console.log('Multisig Max Signatories:', maxSignatories.toHuman());
} catch (error) {
console.error('Error querying max signatories:', error);
} finally {
await api.disconnect();
}
};
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
=== "Example Response"
```
Multisig Max Signatories: 100
```
## How to Create a Multisig Account {: #create-a-multisig-account }
You can easily create a multisig account from the Polkadot.js Apps interface. The easiest way to do so is from the [**Accounts** page](https://polkadot.js.org/apps/?rpc=wss://wss.api.moonbase.moonbeam.network#/accounts){target=\_blank}.
To get started, go ahead and click on **Multisig**.

Next, you can take the following steps:
1. Choose which accounts you want to add to the multisig. For this example, three accounts will be chosen: Alice, Bob, and Charlie
2. Enter a number for **threshold**. This example will use `2`
3. Add a name for the multisig. This example uses `ABC` for Alice, Bob, and Charlie
4. Click **Create**

Now, the ABC multisig account will appear under the **multisig** section on the **Accounts** page.

You can click on the colored icon next to the multisig account to copy the address and fund it with DEV tokens.
You can get DEV tokens for testing on Moonbase Alpha once every 24 hours from the [Moonbase Alpha Faucet](https://faucet.moonbeam.network){target=\_blank}.
## How to Create a Multisig Transaction {: #create-a-multisig-transaction }
Now that you've created a multisig account, you can create a multisig call from one of the accounts that make up the multisig. This example will create the call from Alice's account. As such, Alice will need to submit a deposit. The deposit is calculated as follows:
```text
Deposit = depositBase + threshold * depositFactor
```
You can retrieve the `depositBase` and `depositFactor` using the getter functions for the [Pallet Constants](#constants).
Once the call is approved and dispatched or cancelled the deposit will be returned to Alice.
Since there is a threshold of two for this multisig, at least Bob or Charlie will need to approve the call if not both of them. The last account to approve the call will also need to dispatch the call. Dispatching the call is done automatically when the `asMulti` function is used to approve the call.
With the basics out of the way, you can begin to create a multisig call. For this example, you can create a call that will transfer 0.1 DEV from the ABC multisig account to Charlie's account. First, you'll need to get the encoded call data for the transfer. Go ahead and navigate to the [**Extrinsics** page on Polkadot.js Apps](https://polkadot.js.org/apps/?rpc=wss://wss.api.moonbase.moonbeam.network#/extrinsics){target=\_blank} and take the following steps:
1. Make sure an account is selected. It doesn't have to be the ABC multisig account, as the selected account is not included in the encoded call data
2. Select the **balances** pallet and the **transfer** extrinsic
3. Set Charlie as the **dest** account
4. Enter the amount to transfer, which is `0.1` DEV for this example
5. Click the copy button next to the **encoded call data**
6. Click the copy button next to the **encoded call hash**. Please note that you do not have to submit the extrinsic, you only need the encoded call data and the encoded call hash

Make sure you've copied and saved the encoded call data and the encoded call hash as you'll need them both to approve the multisig call later on in the tutorial. For this example, the encoded call data and hash are as follows:
=== "Encoded call data"
```text
0x0300798d4ba9baf0064ec19eb4f0a1a45785ae9d6dfc1300008a5d78456301
```
=== "Encoded call hash"
```text
0x76d1a0a8f6eb177dd7a561ef954e83893823fa5d77f576910f3fdc6cb4666dea
```
Next, you can create the multisig call by using the `asMulti` extrinsic, you'll take the following steps:
1. Select the account you want to create the call with. For this example, Alice is used
2. Select the **multisig** pallet and the **asMulti** extrinsic
3. Set the threshold of the multisig to the same value as you initially set from the **Accounts** page, which should be `2`
4. Add the other accounts that are associated with the multisig: Bob and Charlie
5. Since this is the first transaction to create the multisig call, make sure the **include option** slider is toggled off for the **maybeTimepoint** field. You would only enter this information for approvals that rely on knowing the timepoint at which the call was created
6. Provide the call information for the balance transfer similarly to how you did it in the previous set of steps. Select the **balances** pallet and the **transfer** extrinsic
7. Set the **dest** account to Charlie
8. Set the **value** to `0.1` DEV tokens
9. You can leave the **refTime** and **proofSize** fields set to `0`
10. Click **Submit Transaction** to create the multisig call

Now that you've created the multisig call, you can submit approval transactions from either Bob's or Charlie's account, or both. Remember, for the call to be approved and dispatched, you need to have at least two of three members of the multisig to approve it. Since Alice created the multisig call, that means she has already automatically approved it.
You can easily approve the transactions through the **Accounts** page of Polkadot.js Apps. Next to your multisig account, you'll notice there is a multisig icon there that you can hover over. Once you hover over it, you'll be able to click on **View pending approvals**.

The **pending call hashes** pop-up will appear where you can follow these steps:
1. Since you should only have one hash at this point, you can select it from this list. If you have multiple hashes, you can compare the hashes in the list with the encoded call hash you copied earlier on in this section
2. The **depositor** should be automatically populated. For this example, it should be Alice
3. For the **approval type**, you can choose to either approve or reject the call. For this example, you can select **Approve this call hash**
4. Choose the account you want to approve the transaction from. This example uses Bob's account
5. Click **Approve** to submit the approval transaction. Under the hood, this uses the `approveAsMulti` extrinsic of the Multisig Pallet

So far, Alice and Bob have approved the multisig call, which means the threshold has been met. However, the call has not been dispatched yet since you have not yet submitted an executing approval. To do so, you'll take the same steps as above plus these additional steps:
1. Select the account you want to approve the transaction from. This example uses Charlie's account
2. Toggle the **multisig message with call (for final approval)** switch to on. Under the hood, this switches the extrinsic to `asMulti`, which automatically approves and dispatches the call if the threshold for approvals has been met as is the case at this point
3. The **call data for final approval** field will appear. Enter the encoded call data that you copied earlier on in this section
4. Click **Approve** to submit the approval, which will also dispatch the multisig call

Once the final transaction has been submitted, 0.1 DEV tokens will be transferred from the ABC multisig account to Charlie's account and the multisig deposit will be returned to Alice's account. And that's it! You've successfully created a multisig call, approved the call, and dispatched it.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/substrate/interfaces/account/proxy/
--- BEGIN CONTENT ---
---
title: Proxy Pallet
description: Learn how to use the available extrinsics, storage methods, and constants in the Proxy Pallet on Moonbeam to make calls on an account's behalf.
keywords: proxy, substrate, moonbeam, polkadot
categories: Substrate Toolkit
---
# The Proxy Pallet
## Introduction {: #introduction }
Proxy accounts can be set up to perform a limited number of actions on behalf of users and are useful for keeping the underlying accounts safe. They allow users to keep their primary account secured safely in cold storage while enabling the proxy to actively perform functions and participate in the network with the weight of the tokens in the primary account.
[Substrate's proxy pallet](https://wiki.polkadot.com/learn/learn-proxies/){target=\_blank} enables you to create proxy accounts, remove proxy accounts, make calls as a proxy account, and announce proxy transactions. To add and remove proxy accounts, you can use the proxy precompile: a Solidity interface that can be interacted through the Ethereum API. For more information on how to use this contract, please refer to the [Proxy Precompile](/builders/ethereum/precompiles/account/proxy/){target=\_blank} guide.
This page will provide an overview of the extrinsics, storage methods, and getters for the pallet constants available in the proxy pallet.
## Proxy Pallet Interface {: #proxy-pallet-interface }
### Extrinsics {: #extrinsics }
The proxy pallet provides the following extrinsics (functions):
??? function "**addProxy**(delegate, proxyType, delay) - registers a proxy account for the sender that is able to make calls on the sender's behalf. If `delay` is set to a value greater than 0, the proxy account will have to announce a transaction and wait that value of blocks before attempting to execute it as a proxy. Emits a `ProxyAdded` event"
=== "Parameters"
- `delegate` - The account that will act as proxy (H160 format address, e.g., '0x123...'). This address will be able to submit transactions on behalf of the caller
- `proxyType` - The permissions granted to the proxy account. Available options are:
- `Any`: Allows all transactions
- `NonTransfer`: Allows all transactions except balance transfers
- `Governance`: Allows governance-related transactions
- `Staking`: Allows staking-related transactions
- `CancelProxy`: Only allows canceling other proxies
- `Balances`: Allows balance transfers
- `AuthorMapping`: Allows author mapping transactions
- `IdentityJudgement`: Allows providing identity judgements
- `delay` - Number of blocks that must pass after announcing a proxy transaction before it can be executed (u32). Set to `0` for immediate execution
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup account from private key
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const account = keyring.addFromUri(PRIVATE_KEY);
// Use an existing account as proxy
const proxyAccount = 'INSERT_PROXY_ACCOUNT';
// Define proxy parameters
// Use the Staking variant from the ProxyType enum
const proxyType = { Staking: null };
const delay = 0; // No delay
console.log('Validation checks:');
console.log('Account address:', account.address);
console.log('Proxy account address:', proxyAccount);
console.log('Proxy type:', JSON.stringify(proxyType));
console.log('Delay:', delay);
// Create the addProxy transaction
const tx = api.tx.proxy.addProxy(proxyAccount, proxyType, delay);
// Sign and send the transaction
await tx.signAndSend(account, ({ status, events }) => {
if (status.isInBlock) {
console.log(`Transaction included in block hash: ${status.asInBlock}`);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful proxy addition
if (section === 'proxy' && method === 'ProxyAdded') {
console.log('Proxy successfully added!');
}
});
process.exit(0);
}
});
} catch (error) {
console.error('Error in adding proxy:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
=== "Example Response"
```
Validation checks:
Account address: 0x3B939FeaD1557C741Ff06492FD0127bd287A421e
Proxy account address: 0x569BE8d8b04538318e1722f6e375FD381D2da865
Proxy type: {"Staking":null}
Delay: 0
Transaction included in block hash: 0xd9763b3eec3e50dfeec246f1537421a632ec5a3ab821a5e5e6b507c12930cd64
balances.Withdraw: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",3431276154061]
balances.Reserved: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",2100000000000000]
proxy.ProxyAdded: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e","0x569BE8d8b04538318e1722f6e375FD381D2da865","Staking",0]
Proxy successfully added!
balances.Deposit: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",0]
balances.Deposit: ["0x6d6F646c70632f74727372790000000000000000",686255230813]
transactionPayment.TransactionFeePaid: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",3431276154061,0]
system.ExtrinsicSuccess: [{"weight":{"refTime":398219506,"proofSize":4310},"class":"Normal","paysFee":"Yes"}]
```
??? function "**announce**(real, callHash) - registers an announcement of a proxy transaction by proxy accounts that require a delay. Emits an `Announced` event"
=== "Parameters"
- `real` - The account being proxied (H160 format address, e.g., '0x123...'). This is the account on whose behalf the delayed proxy intends to execute a call
- `callHash` - The hash of the call that the proxy intends to execute after the delay period (32-byte hex string, e.g., '0x570ff355...'). This hash is derived from the actual call data that will be executed later
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup accounts
const PROXY_PRIVATE_KEY = 'INSERT_PROXY_PRIVATE_KEY';
const proxyAccount = keyring.addFromUri(PROXY_PRIVATE_KEY);
// The real account that the proxy will act on behalf of
const realAccount = 'INSERT_REAL_ACCOUNT';
// Use the provided call hash
const callHash = 'INSERT_CALL_HASH';
console.log('Validation checks:');
console.log('Proxy account address:', proxyAccount.address);
console.log('Real account address:', realAccount);
console.log('Call hash:', callHash);
// Create the announce transaction
const tx = api.tx.proxy.announce(realAccount, callHash);
// Sign and send the transaction
await tx.signAndSend(proxyAccount, ({ status, events }) => {
if (status.isInBlock) {
console.log(`Transaction included in block hash: ${status.asInBlock}`);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful announcement
if (section === 'proxy' && method === 'Announced') {
console.log('Proxy call successfully announced!');
console.log(
'You can execute the actual call after the delay period'
);
}
});
process.exit(0);
}
});
} catch (error) {
console.error('Error in announcing proxy call:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
=== "Example Response"
```
Validation checks:
Proxy account address: 0x569BE8d8b04538318e1722f6e375FD381D2da865
Real account address: 0x3B939FeaD1557C741Ff06492FD0127bd287A421e
Call hash: 0x570ff355e1471d3528cb4e2586bee7eafebc2efc89dd6f827188c69b15fff965
Transaction included in block hash: 0xdb5b9bb961ce3153387d2131911de218c08b8b09d8a625f36271ad98b2abf567
balances.Withdraw: ["0x569BE8d8b04538318e1722f6e375FD381D2da865",3682233905542]
balances.Reserved: ["0x569BE8d8b04538318e1722f6e375FD381D2da865","0x00000000000000000df77377c5f40000"]
proxy.Announced: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e","0x569BE8d8b04538318e1722f6e375FD381D2da865","0x570ff355e1471d3528cb4e2586bee7eafebc2efc89dd6f827188c69b15fff965"]
Proxy call successfully announced!
You can execute the actual call after the delay period
balances.Deposit: ["0x569BE8d8b04538318e1722f6e375FD381D2da865",0]
balances.Deposit: ["0x6d6F646c70632f74727372790000000000000000",736446781109]
transactionPayment.TransactionFeePaid: ["0x569BE8d8b04538318e1722f6e375FD381D2da865",3682233905542,0]
system.ExtrinsicSuccess: [{"weight":{"refTime":577384531,"proofSize":5302},"class":"Normal","paysFee":"Yes"}]
```
??? function "**proxy**(real, forceProxyType, call) - makes a transaction as a proxy. Emits a `ProxyExecuted` event"
=== "Parameters"
- `real` - The account being proxied (H160 format address, e.g., '0x123...'). This is the account on whose behalf the proxy will execute the call
- `forceProxyType` - The type of proxy right required to execute this call. Must match the proxy type that was specified when the proxy was added. Available options are:
- `Any`: Allows all transactions
- `NonTransfer`: Allows all transactions except balance transfers
- `Governance`: Allows governance-related transactions
- `Staking`: Allows staking-related transactions
- `CancelProxy`: Only allows canceling other proxies
- `Balances`: Allows balance transfers
- `AuthorMapping`: Allows author mapping transactions
- `IdentityJudgement`: Allows providing identity judgements
- `call` - The actual call data to be executed by the proxy on behalf of the real account. This is the transaction that will be performed (e.g., a transfer, a stake, or any other valid runtime call)
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup proxy account from private key
const PROXY_PRIVATE_KEY = 'INSERT_PROXY_PRIVATE_KEY';
const proxyAccount = keyring.addFromUri(PROXY_PRIVATE_KEY);
// The real account that we're making the transaction for
const realAccount = 'INSERT_REAL_ACCOUNT';
// Destination account for the simple demo transfer
const destinationAccount = 'INSERT_DESTINATION_ADDRESS';
// Amount to transfer (1 DEV = 1e18 Wei)
const transferAmount = '1000000000000000000'; // 1 DEV
// Create the transfer call that we want to make via proxy
const transferCall = api.tx.balances.transferAllowDeath(
destinationAccount,
transferAmount
);
// Create the proxy transaction
// We'll specify Balances as the force proxy type since we're doing a transfer
const tx = api.tx.proxy.proxy(
realAccount,
{ Any: null }, // forceProxyType
transferCall
);
console.log('Validation checks:');
console.log('Proxy account:', proxyAccount.address);
console.log('Real account:', realAccount);
console.log('Destination account:', destinationAccount);
console.log('Transfer amount:', transferAmount, 'Wei (1 DEV)');
// Sign and send the transaction
await tx.signAndSend(proxyAccount, ({ status, events }) => {
if (status.isInBlock) {
console.log(`Transaction included in block hash: ${status.asInBlock}`);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful transfer
if (section === 'balances' && method === 'Transfer') {
console.log('\nTransfer successfully executed via proxy!');
const [from, to, amount] = data;
console.log('From:', from.toString());
console.log('To:', to.toString());
console.log('Amount:', amount.toString());
}
});
process.exit(0);
}
});
} catch (error) {
console.error('Error in proxy transaction:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
=== "Example Response"
```
Validation checks:
Proxy account: 0x3B939FeaD1557C741Ff06492FD0127bd287A421e
Real account: 0x569BE8d8b04538318e1722f6e375FD381D2da865
Destination account: 0x8c9c5F11d162a69E979F2DB9047A862ecbcA23Cb
Transfer amount: 1000000000000000000 Wei (1 DEV)
Force proxy type: Balances
Transaction included in block hash: 0xc347d714324e795c0e27ef574c8f924d7a52935314044cf2e2a395bc32ef5070
balances.Withdraw: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",3817444390449]
balances.Transfer: ["0x569BE8d8b04538318e1722f6e375FD381D2da865","0x8c9c5F11d162a69E979F2DB9047A862ecbcA23Cb","0x00000000000000000de0b6b3a7640000"]
Transfer successfully executed via proxy!
From: 0x569BE8d8b04538318e1722f6e375FD381D2da865
To: 0x8c9c5F11d162a69E979F2DB9047A862ecbcA23Cb
Amount: 1000000000000000000
proxy.ProxyExecuted: [{"ok":null}]
balances.Deposit: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",0]
balances.Deposit: ["0x6d6F646c70632f74727372790000000000000000",763488878090]
transactionPayment.TransactionFeePaid: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",3817444390449,0]
system.ExtrinsicSuccess: [{"weight":{"refTime":684752866,"proofSize":8691},"class":"Normal","paysFee":"Yes"}]
```
??? function "**proxyAnnounced**(delegate, real, forceProxyType, call) - makes a transaction as a proxy and removes previous corresponding announcements. Emits a `ProxyExecuted` event"
=== "Parameters"
- `delegate` - The account that previously made the announcement (H160 format address, e.g., '0x123...'). This must match the proxy account that called the announce function
- `real` - The account being proxied (H160 format address, e.g., '0x123...'). This is the account on whose behalf the proxy will execute the call
- `forceProxyType` - The type of proxy right required to execute this call. Must match the proxy type that was specified when the proxy was added. Available options are:
- `Any`: Allows all transactions
- `NonTransfer`: Allows all transactions except balance transfers
- `Governance`: Allows governance-related transactions
- `Staking`: Allows staking-related transactions
- `CancelProxy`: Only allows canceling other proxies
- `Balances`: Allows balance transfers
- `AuthorMapping`: Allows author mapping transactions
- `IdentityJudgement`: Allows providing identity judgements
- `call` - The actual call to be executed (must match the call that was previously announced). This is the transaction that will be performed (e.g., a transfer, a stake, or any other valid runtime call)
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup proxy account from private key (this is the account executing the call)
const PROXY_PRIVATE_KEY = 'INSERT_PROXY_PRIVATE_KEY';
const proxyAccount = keyring.addFromUri(PROXY_PRIVATE_KEY);
// The account that delegated proxy rights
const realAccount = 'INSERT_REAL_ACCOUNT';
// The delegate account (the proxy account that made the announcement)
const delegateAccount = proxyAccount.address;
// Destination account for the transfer
const destinationAccount = 'INSERT_DESTINATION_ADDRESS';
// Amount to transfer (1 DEV = 1e18 Wei)
const transferAmount = '1000000000000000000'; // 1 DEV
// Create the transfer call that was previously announced
const transferCall = api.tx.balances.transferAllowDeath(
destinationAccount,
transferAmount
);
// Create the proxyAnnounced transaction
const tx = api.tx.proxy.proxyAnnounced(
delegateAccount,
realAccount,
{ Balances: null }, // forceProxyType
transferCall
);
console.log('Validation checks:');
console.log('Delegate (Proxy) account:', delegateAccount);
console.log('Real account:', realAccount);
console.log('Force proxy type: Balances');
console.log('Call details:');
console.log('- Destination:', destinationAccount);
console.log('- Amount:', transferAmount, 'Wei (1 DEV)');
// Sign and send the transaction
await tx.signAndSend(proxyAccount, ({ status, events }) => {
if (status.isInBlock) {
console.log(`Transaction included in block hash: ${status.asInBlock}`);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful proxy execution
if (section === 'proxy' && method === 'ProxyExecuted') {
console.log('\nProxy call successfully executed!');
}
// Log successful transfer
if (section === 'balances' && method === 'Transfer') {
const [from, to, amount] = data;
console.log('Transfer details:');
console.log('From:', from.toString());
console.log('To:', to.toString());
console.log('Amount:', amount.toString());
}
});
process.exit(0);
}
});
} catch (error) {
console.error('Error in proxy announced transaction:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
=== "Example Response"
```
Validation checks:
Proxy account: 0x3B939FeaD1557C741Ff06492FD0127bd287A421e
Real account: 0x569BE8d8b04538318e1722f6e375FD381D2da865
Destination account: 0x8c9c5F11d162a69E979F2DB9047A862ecbcA23Cb
Transfer amount: 1000000000000000000 Wei (1 DEV)
Force proxy type: Balances
Transaction included in block hash: 0xc347d714324e795c0e27ef574c8f924d7a52935314044cf2e2a395bc32ef5070
balances.Withdraw: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",3817444390449]
balances.Transfer: ["0x569BE8d8b04538318e1722f6e375FD381D2da865","0x8c9c5F11d162a69E979F2DB9047A862ecbcA23Cb","0x00000000000000000de0b6b3a7640000"]
Transfer successfully executed via proxy!
From: 0x569BE8d8b04538318e1722f6e375FD381D2da865
To: 0x8c9c5F11d162a69E979F2DB9047A862ecbcA23Cb
Amount: 1000000000000000000
proxy.ProxyExecuted: [{"ok":null}]
balances.Deposit: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",0]
balances.Deposit: ["0x6d6F646c70632f74727372790000000000000000",763488878090]
transactionPayment.TransactionFeePaid: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",3817444390449,0]
system.ExtrinsicSuccess: [{"weight":{"refTime":684752866,"proofSize":8691},"class":"Normal","paysFee":"Yes"}]
```
??? function "**rejectAnnouncement**(delegate, callHash) - if the sender is a prime account, this removes a specific announcement from their proxy account"
=== "Parameters"
- `delegate` - The account that previously made the announcement (H160 format address, e.g., '0x123...'). This must match the proxy account that called the announce function
- `callHash` - The hash call to be executed (must match the call that was previously announced)
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup the real account (the one that will reject the announcement)
const REAL_PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const realAccount = keyring.addFromUri(REAL_PRIVATE_KEY);
// The proxy account that made the announcement
const delegateAccount = 'INSERT_PROXY_ACCOUNT';
// The call hash of the announcement to reject
const callHash = 'INSERT_CALL_HASH';
console.log('Validation checks:');
console.log('Real account (rejector):', realAccount.address);
console.log('Delegate account to reject:', delegateAccount);
console.log('Call hash to reject:', callHash);
// Create the reject announcement transaction
const tx = api.tx.proxy.rejectAnnouncement(delegateAccount, callHash);
// Sign and send the transaction
await tx.signAndSend(realAccount, ({ status, events }) => {
if (status.isInBlock) {
console.log(`Transaction included in block hash: ${status.asInBlock}`);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful rejection
if (section === 'proxy' && method === 'AnnouncementRejected') {
console.log('\nAnnouncement successfully rejected!');
const [accountId, hash] = data;
console.log('Rejected delegate:', accountId.toString());
console.log('Rejected call hash:', hash.toString());
}
});
process.exit(0);
}
});
} catch (error) {
console.error('Error in rejecting announcement:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
=== "Example Response"
Validation checks:
Real account (rejector): 0x569BE8d8b04538318e1722f6e375FD381D2da865
Delegate account to reject: 0x569BE8d8b04538318e1722f6e375FD381D2da865
Call hash to reject: 0xaf2dd398c8ee31d963d1f24764b8857e27314b3e937385c3ff60c034a36e925c
Transaction included in block hash: 0x76073a7b5eae1b9efb4a8142916fb33fa9f11a31f9e1f231ecb1ebd1af7a2a47
balances.Withdraw: ["0x569BE8d8b04538318e1722f6e375FD381D2da865",3621382860542]
balances.Deposit: ["0x569BE8d8b04538318e1722f6e375FD381D2da865",0]
balances.Deposit: ["0x6d6F646c70632f74727372790000000000000000",724276572109]
transactionPayment.TransactionFeePaid: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",3621382860542,0]
["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",3817444390449,0]
system.ExtrinsicSuccess: [{"weight":{"refTime":684752866,"proofSize":8691},"class":"Normal","paysFee":"Yes"}]
??? function "**removeAnnouncement**(real, callHash) - if the sender is a proxy account, this removes a specific announcement to their prime account"
=== "Parameters"
- `real` - The account that was designated as the real account in the original announcement (H160 format address, e.g., '0x123...'). This is the account on whose behalf the proxy had announced a future transaction
- `callHash` - The hash of the call from the original announcement (32-byte hex string, e.g., '0x570ff355...'). This uniquely identifies which announced transaction should be removed
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup the proxy account (the one that will remove its own announcement)
const PROXY_PRIVATE_KEY = 'INSERT_PROXY_PRIVATE_KEY';
const proxyAccount = keyring.addFromUri(PROXY_PRIVATE_KEY);
// The real account that the announcement was made for
const realAccount = 'INSERT_REAL_ACCOUNT';
// The call hash of the announcement to remove
const callHash = 'INSERT_CALL_HASH';
console.log('Validation checks:');
console.log('Proxy account (remover):', proxyAccount.address);
console.log('Real account:', realAccount);
console.log('Call hash to remove:', callHash);
// Create the remove announcement transaction
const tx = api.tx.proxy.removeAnnouncement(realAccount, callHash);
// Sign and send the transaction
await tx.signAndSend(proxyAccount, ({ status, events }) => {
if (status.isInBlock) {
console.log(`Transaction included in block hash: ${status.asInBlock}`);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful announcement removal
if (section === 'proxy' && method === 'AnnouncementRejected') {
console.log('\nAnnouncement successfully removed!');
const [accountId, hash] = data;
console.log('Removed for real account:', accountId.toString());
console.log('Removed call hash:', hash.toString());
}
});
process.exit(0);
}
});
} catch (error) {
console.error('Error in removing announcement:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
=== "Example Response"
```
Validation checks:
Proxy account (remover): 0x3B939FeaD1557C741Ff06492FD0127bd287A421e
Real account: 0x569BE8d8b04538318e1722f6e375FD381D2da865
Call hash to remove: 0x570ff355e1471d3528cb4e2586bee7eafebc2efc89dd6f827188c69b15fff965
Transaction included in block hash: 0x767724a583d93b558c56f2e241d2334bf91773269ceb1e0a60435f7cbbe2205a
balances.Withdraw: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",3621330308042]
balances.Deposit: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",0]
balances.Deposit: ["0x6d6F646c70632f74727372790000000000000000",724266061609]
transactionPayment.TransactionFeePaid: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",3621330308042,0]
["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",3817444390449,0]
system.ExtrinsicSuccess: [{"weight":{"refTime":684752866,"proofSize":8691},"class":"Normal","paysFee":"Yes"}]
```
??? function "**removeProxies**() - unregisters all proxy accounts for the sender"
=== "Parameters"
None
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup the account that wants to remove all its proxies
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const account = keyring.addFromUri(PRIVATE_KEY);
console.log('Validation checks:');
console.log('Account removing all proxies:', account.address);
// Optional: Query existing proxies before removal
const proxies = await api.query.proxy.proxies(account.address);
console.log('\nCurrent proxies before removal:', proxies.toHuman());
// Create the removeProxies transaction
const tx = api.tx.proxy.removeProxies();
// Sign and send the transaction
await tx.signAndSend(account, ({ status, events }) => {
if (status.isInBlock) {
console.log(
`\nTransaction included in block hash: ${status.asInBlock}`
);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful proxy removals
if (section === 'proxy' && method === 'ProxyRemoved') {
console.log('\nProxy successfully removed!');
const [delegator, delegate, proxyType, delay] = data;
console.log('Delegator:', delegator.toString());
console.log('Removed delegate:', delegate.toString());
console.log('Proxy type:', proxyType.toString());
console.log('Delay:', delay.toString());
}
});
// Optional: Query proxies after removal to confirm
api.query.proxy.proxies(account.address).then((afterProxies) => {
console.log('\nProxies after removal:', afterProxies.toHuman());
process.exit(0);
});
}
});
} catch (error) {
console.error('Error in removing all proxies:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
=== "Example Response"
```
Validation checks:
Account removing all proxies: 0x3B939FeaD1557C741Ff06492FD0127bd287A421e
Current proxies before removal: [
[
{
delegate: '0x0000000000000000000000000000000000000000',
proxyType: 'Governance',
delay: '0'
},
{
delegate: '0x4b8C667590E6a28497Ea4be5FACB7e9869A64EAE',
proxyType: 'Staking',
delay: '0'
},
{
delegate: '0x569BE8d8b04538318e1722f6e375FD381D2da865',
proxyType: 'Staking',
delay: '0'
},
{
delegate: '0x569BE8d8b04538318e1722f6e375FD381D2da865',
proxyType: 'Balances',
delay: '100'
}
],
'1,009,200,000,000,000,000'
]
Transaction included in block hash: 0x2ef80fe655c98f47ba82cc2ee7937e03d2c6211195dc03ef02e6d47fbbdcd944
balances.Withdraw: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",3403192090986]
balances.Unreserved: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e","0x00000000000000000e01660d93530000"]
balances.Deposit: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",0]
balances.Deposit: ["0x6d6F646c70632f74727372790000000000000000",680638418198]
transactionPayment.TransactionFeePaid: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",3403192090986,0]
system.ExtrinsicSuccess: [{"weight":{"refTime":395752965,"proofSize":4310},"class":"Normal","paysFee":"Yes"}]
Proxies after removal: [ [], '0' ]
```
??? function "**removeProxy**(delegate, proxyType, delay) - unregisters a specific proxy account for the sender. Emits a `ProxyRemoved` event"
=== "Parameters"
- `delegate` - The proxy account to remove (H160 format address, e.g., '0x123...'). This must be an existing proxy account that was previously registered using addProxy
- `proxyType` - The type of proxy to remove. Must match exactly what was set when the proxy was added. Available options are:
- `Any`: Allows all transactions
- `NonTransfer`: Allows all transactions except balance transfers
- `Governance`: Allows governance-related transactions
- `Staking`: Allows staking-related transactions
- `CancelProxy`: Only allows canceling other proxies
- `Balances`: Allows balance transfers
- `AuthorMapping`: Allows author mapping transactions
- `IdentityJudgement`: Allows providing identity judgements
- `delay` - The announcement delay in blocks that was set when adding the proxy (u32). Must match exactly what was set when the proxy was added (e.g., if proxy was added with delay=100, must use delay=100 to remove it)
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup the account that wants to remove a specific proxy
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const account = keyring.addFromUri(PRIVATE_KEY);
// The proxy account to remove
const proxyToRemove = 'INSERT_PROXY_ACCOUNT';
// Must match the original proxy type and delay that was set when adding the proxy
const proxyType = { Any: null };
const delay = 0;
console.log('Validation checks:');
console.log('Account removing proxy:', account.address);
console.log('Proxy being removed:', proxyToRemove);
console.log('Proxy type:', JSON.stringify(proxyType));
console.log('Delay:', delay);
// Optional: Query existing proxies before removal
const proxiesBefore = await api.query.proxy.proxies(account.address);
console.log('\nCurrent proxies before removal:', proxiesBefore.toHuman());
// Create the removeProxy transaction
const tx = api.tx.proxy.removeProxy(proxyToRemove, proxyType, delay);
// Sign and send the transaction
await tx.signAndSend(account, ({ status, events }) => {
if (status.isInBlock) {
console.log(
`\nTransaction included in block hash: ${status.asInBlock}`
);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful proxy removal
if (section === 'proxy' && method === 'ProxyRemoved') {
console.log('\nProxy successfully removed!');
const [delegator, delegate, proxyType, delay] = data;
console.log('Delegator:', delegator.toString());
console.log('Removed delegate:', delegate.toString());
console.log('Proxy type:', proxyType.toString());
console.log('Delay:', delay.toString());
}
});
// Optional: Query proxies after removal to confirm
api.query.proxy.proxies(account.address).then((afterProxies) => {
console.log('\nProxies after removal:', afterProxies.toHuman());
process.exit(0);
});
}
});
} catch (error) {
console.error('Error in removing proxy:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
=== "Example Response"
```
Validation checks:
Account removing proxy: 0x3B939FeaD1557C741Ff06492FD0127bd287A421e
Proxy being removed: 0x569BE8d8b04538318e1722f6e375FD381D2da865
Proxy type: {"Any":null}
Delay: 0
Current proxies before removal: [
[
{
delegate: '0x569BE8d8b04538318e1722f6e375FD381D2da865',
proxyType: 'Any',
delay: '0'
}
],
'1,002,900,000,000,000,000'
]
Transaction included in block hash: 0x8402c11ca656798ad54eea16c5c05b5fefa5d5d23beb590d214d2fa4168d8af9
balances.Withdraw: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",3431367169061]
balances.Unreserved: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e","0x00000000000000000deb043c853d4000"]
proxy.ProxyRemoved: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e","0x569BE8d8b04538318e1722f6e375FD381D2da865","Any",0]
Proxy successfully removed!
Delegator: 0x3B939FeaD1557C741Ff06492FD0127bd287A421e
Removed delegate: 0x569BE8d8b04538318e1722f6e375FD381D2da865
Proxy type: Any
Delay: 0
balances.Deposit: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",0]
balances.Deposit: ["0x6d6F646c70632f74727372790000000000000000",686273433813]
transactionPayment.TransactionFeePaid: ["0x3B939FeaD1557C741Ff06492FD0127bd287A421e",3431367169061,0]
system.ExtrinsicSuccess: [{"weight":{"refTime":398292318,"proofSize":4310},"class":"Normal","paysFee":"Yes"}]
Proxies after removal: [ [], '0' ]
```
!!! note
Anonymous proxies are disabled on Moonbeam networks because they are easy to misuse. Incorrect usage can cause a permanent loss of funds and unreserved balances.
### Storage Methods {: #storage-methods }
The proxy pallet includes the following read-only storage methods to obtain chain state data:
??? function "**announcements**(AccountId20) - returns all announcements made by the specified proxy account"
=== "Parameters"
- `AccountId20` - The proxy account's address in H160 format (e.g., '0x123...') whose announcements you want to query
=== "Returns"
Returns a tuple containing:
- Array of announcements, each containing:
- real: AccountId20 (The account the announcement was made for)
- callHash: H256 (The hash of the announced call)
- height: BlockNumber (The block number when announced)
- Balance (The amount reserved to place the announcements)
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
try {
// Initialize connection to the network
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// The proxy address to query
const proxyAddress = 'INSERT_PROXY_ACCOUNT';
// Query announcements
const announcements = await api.query.proxy.announcements(proxyAddress);
// Log the results
console.log('Querying announcements for proxy:', proxyAddress);
console.log(
'\nAnnouncements:',
JSON.stringify(announcements.toHuman(), null, 2)
);
process.exit(0);
} catch (error) {
console.error('Error occurred:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**palletVersion**() - returns the current pallet version"
=== "Parameters"
- None
=== "Returns"
Returns a single number representing the current version of the proxy pallet
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
try {
// Initialize connection to the network
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Query pallet version
const version = await api.query.proxy.palletVersion();
// Log the result
console.log('Proxy Pallet Version:', version.toHuman());
process.exit(0);
} catch (error) {
console.error('Error occurred:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**proxies**(AccountId20) - returns a map and count of all proxy accounts for a specified primary account"
=== "Parameters"
- `AccountId20` - The primary account's address in H160 format (e.g., '0x123...') whose proxies you want to query
=== "Returns"
Returns a tuple containing:
- Array of ProxyDefinition, each containing:
- delegate: AccountId20 (The proxy account address)
- proxyType: Enum (The type of proxy)
- delay: Number (The announcement delay in blocks)
- Balance (The amount reserved to place the proxies)
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
try {
// Initialize connection to the network
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// The account address to query proxies for
const accountAddress = 'INSERT_REAL_ACCOUNT';
// Query proxies
const [proxies, deposit] = await api.query.proxy.proxies(accountAddress);
// Log the results with formatted JSON
console.log('Querying proxies for account:', accountAddress);
console.log('\nProxies:', JSON.stringify(proxies.toHuman(), null, 2));
console.log('Required deposit:', deposit.toHuman());
// Display in a more readable format
console.log('\nProxy Details:');
proxies.forEach((proxy, index) => {
console.log(`\nProxy #${index + 1}:`);
console.log(' Delegate:', proxy.delegate.toString());
console.log(' Proxy Type:', proxy.proxyType.toString());
console.log(' Delay:', proxy.delay.toString());
});
process.exit(0);
} catch (error) {
console.error('Error occurred:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
### Pallet Constants {: #constants }
The proxy pallet includes the following read-only functions to obtain pallet constants:
??? function "**announcementDepositBase**() - returns the base amount of currency needed to reserve for creating an announcement"
=== "Parameters"
- None
=== "Returns"
Returns a Balance value representing the base deposit amount in Wei required for creating a proxy announcement
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Query the base deposit
const baseDeposit = await api.consts.proxy.announcementDepositBase;
console.log('Announcement Base Deposit:', baseDeposit.toHuman());
process.exit(0);
};
main().catch(console.error);
```
??? function "**announcementDepositFactor**() - returns the amount of currency needed per announcement made"
=== "Parameters"
None
=== "Returns"
Returns a Balance value representing the additional deposit amount in Wei required for each announcement made
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Query the deposit factor
const depositFactor = await api.consts.proxy.announcementDepositFactor;
console.log('Announcement Deposit Factor:', depositFactor.toHuman());
process.exit(0);
};
main().catch(console.error);
```
??? function "**maxPending**() - returns the maximum amount of time-delayed announcements that are allowed to be pending"
=== "Parameters"
None
=== "Returns"
Returns a u32 value representing the maximum number of announcements that can be pending for a proxy account
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Query max pending announcements
const maxPending = await api.consts.proxy.maxPending;
console.log('Maximum Pending Announcements:', maxPending.toHuman());
process.exit(0);
};
main().catch(console.error);
```
??? function "**maxProxies**() - returns the maximum amount of proxies allowed for a single account"
=== "Parameters"
None
=== "Returns"
Returns a u32 value representing the maximum number of proxy accounts that can be registered to a single account
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Query max proxies allowed
const maxProxies = await api.consts.proxy.maxProxies;
console.log('Maximum Proxies per Account:', maxProxies.toHuman());
process.exit(0);
};
main().catch(console.error);
```
??? function "**proxyDepositBase**() - returns the base amount of currency needed to reserve for creating a proxy"
=== "Parameters"
None
=== "Returns"
Returns a Balance value representing the base deposit amount in Wei required for creating a proxy
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Query the base deposit for proxy creation
const baseDeposit = await api.consts.proxy.proxyDepositBase;
console.log('Proxy Base Deposit:', baseDeposit.toHuman());
process.exit(0);
};
main().catch(console.error);
```
??? function "**proxyDepositFactor**() - returns the amount of currency needed per proxy added"
=== "Parameters"
None
=== "Returns"
Returns a Balance value representing the additional deposit amount in Wei required for each proxy registered
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Query the deposit factor for proxies
const depositFactor = await api.consts.proxy.proxyDepositFactor;
console.log('Proxy Deposit Factor:', depositFactor.toHuman());
process.exit(0);
};
main().catch(console.error);
```
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/substrate/interfaces/features/governance/conviction-voting/
--- BEGIN CONTENT ---
---
title: Conviction Voting Pallet
description: This guide covers the available functions in the Conviction Voting Pallet on Moonbeam, which are used to vote, delegate votes, remove votes, and more.
keywords: democracy, substrate, pallet, moonbeam, polkadot, voting, vote, referenda
categories: Substrate Toolkit
---
# The Conviction Voting Pallet
## Introduction {: #introduction }
The Conviction Voting Pallet allows token holders to make, delegate, and manage Conviction-weighted votes on referenda.
Governance-related functionality is based on three new pallets and precompiles: the [Preimage Pallet](/builders/substrate/interfaces/features/governance/preimage/){target=\_blank} and [Preimage Precompile](/builders/ethereum/precompiles/features/governance/preimage/){target=\_blank}, the [Referenda Pallet](/builders/substrate/interfaces/features/governance/referenda/){target=\_blank} and [Referenda Precompile](/builders/ethereum/precompiles/features/governance/referenda/){target=\_blank}, and the [Conviction Voting Pallet](/builders/substrate/interfaces/features/governance/conviction-voting/){target=\_blank} and [Conviction Voting Precompile](/builders/ethereum/precompiles/features/governance/conviction-voting/){target=\_blank}. The aforementioned precompiles are Solidity interfaces that enable you to perform governance functions using the Ethereum API.
This guide will provide an overview of the extrinsics, storage methods, and getters for the pallet constants available in the Conviction Voting Pallet on Moonbeam on Moonbeam. This guide assumes you are familiar with governance-related terminology; if not, please check out the [governance overview page](/learn/features/governance/#opengov){target=_blank} for more information.
## Conviction Voting Pallet Interface {: #preimage-pallet-interface }
### Extrinsics {: #extrinsics }
The Conviction Voting Pallet provides the following extrinsics (functions):
??? function "**delegate**(class, to, conviction, balance) - delegate the voting power (with some given Conviction) to another account for a particular class (Origin and, by extension, Track) of polls (referenda). The balance delegated is locked for as long as it's delegated, and thereafter for the time appropriate for the Conviction's lock period. Emits a `Delegated` event"
=== "Parameters"
- `class` - the index of the Track that the delegate account is permitted to vote on proposals for. The index for each Track is as follows:
- `0` - Root Track
- `1` - Whitelisted Track
- `2` - General Admin Track
- `3` - Emergency Canceller Track
- `4` - Emergency Killer Track
- `to` - the account to delegate voting power to
- `conviction` - the [Conviction multiplier](/learn/features/governance#conviction-multiplier-v2){target=_blank} value to use for the delegation. You can specify either the name of the Conviction multiplier value or the index associated with the value:
- `'None'` or `0`
- `'Locked1x'` or `1`
- `'Locked2x'` or `2`
- `'Locked3x'` or `3`
- `'Locked4x'` or `4`
- `'Locked5x'` or `5`
- `'Locked6x'` or `6`
- `balance` -the number of tokens to delegate to the other account in Wei
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const classIndex = INSERT_TRACK_INDEX;
const to = INSERT_DELEGATE_ACCOUNT;
const conviction = INSERT_CONVICTION;
const balance = INSERT_BALANCE_TO_DELEGATE;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.convictionVoting.delegate(
classIndex,
to,
conviction,
balance
);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**removeOtherVote**(target, class, index) - removes a vote for a poll (referendum). If the `target` is equal to the signer, then this function is exactly equivalent to `removeVote`. If not equal to the signer, then the vote must have expired, either because the poll was canceled, the voter lost the poll, or because the Conviction period is over"
=== "Parameters"
- `target` - the voter to remove the vote for
- `class` - the index of the Track the poll belongs to. The index for each Track is as follows:
- `0` - Root Track
- `1` - Whitelisted Track
- `2` - General Admin Track
- `3` - Emergency Canceller Track
- `4` - Emergency Killer Track
- `index` - the index of the poll (referendum)
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const target = INSERT_ADDRESS;
const classIndex = INSERT_TRACK_INDEX;
const index = INSERT_REFERENDUM_INDEX;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.convictionVoting.removeOtherVote(target, classIndex, index);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**removeVote**(class, index) - removes a vote for a poll"
This can occur if one of the following is true:
- If the poll was canceled, tokens are immediately available for unlocking if there is no other pending lock
- If the poll is ongoing, the token holder's votes no longer count for the tallying, and tokens are immediately available for unlocking if there is no other pending lock
- If the poll has ended, there are two different scenarios:
- If the token holder voted against the tallied result or voted with no Conviction, the tokens are immediately available for unlocking if there is no other pending lock
- If, however, the poll has ended and the results coincide with the vote of the token holder (with a given Conviction) and the lock period of the Conviction is not over, then the lock will be aggregated into the overall account's lock. This may involve _overlocking_ (where the two locks are combined into a single lock that is the maximum of both the amount locked and the time it is locked)
=== "Parameters"
- `class` - the index of the Track the poll belongs to. The index for each Track is as follows:
- `0` - Root Track
- `1` - Whitelisted Track
- `2` - General Admin Track
- `3` - Emergency Canceller Track
- `4` - Emergency Killer Track
- `index` - the index of the poll (referendum)
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const classIndex = INSERT_TRACK_INDEX;
const index = INSERT_REFERENDUM_INDEX;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.convictionVoting.removeVote(classIndex, index);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**undelegate**(class) - undelegates the voting power for a particular class (Origin and, by extension, Track) of polls (referenda). Tokens may be unlocked after an amount of time consistent with the lock period of the Conviction with which the delegation was issued. Emits an `Undelegated` event"
=== "Parameters"
- `class` - the index of the Track to remove the voting power for. The index for each Track is as follows:
- `0` - Root Track
- `1` - Whitelisted Track
- `2` - General Admin Track
- `3` - Emergency Canceller Track
- `4` - Emergency Killer Track
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const classIndex = INSERT_TRACK_INDEX;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.convictionVoting.undelegate(classIndex);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**unlock**(class, target) - removes a lock for a prior vote or delegation vote within a particular class (Origin and, by extension, Track), which has expired"
=== "Parameters"
- `class` - the index of the Track that the poll is assigned to. The index for each Track is as follows:
- `0` - Root Track
- `1` - Whitelisted Track
- `2` - General Admin Track
- `3` - Emergency Canceller Track
- `4` - Emergency Killer Track
- `target` - the account to remove the lock for
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const classIndex = INSERT_TRACK_INDEX;
const target = INSERT_ADDRESS;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.convictionVoting.unlock(classIndex, target);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**vote**(pollIndex, vote) - submits a vote in a poll (referendum). If the vote is "Aye", the vote is to enact the proposal; if it is a "Nay", the vote is to keep the status quo"
=== "Parameters"
- `pollIndex` - the index of the poll (referendum)
- `vote` - the vote and the amount to lock for the vote. There are three types of votes:
- `Standard` - votes a Conviction-weighted vote, with a given amount locked for "Aye" or "Nay". To use `Standard`, you'll have to specify the following:
- `aye` - a boolean indicating whether the vote is an "Aye" or a "Nay"
- `conviction` - the [Conviction multiplier](/learn/features/governance#conviction-multiplier-v2){target=_blank} value to use for the delegation. You can specify either the name of the Conviction multiplier value or the index associated with the value:
- `0` or `'None'`
- `1` or `'Locked1x'`
- `2` or `'Locked2x'`
- `3` or `'Locked3x'`
- `4` or `'Locked4x'`
- `5` or `'Locked5x'`
- `6` or `'Locked6x'`
- balance - the number of tokens to lock for the vote
- `Split` - votes a split vote, with a given amount locked for "Aye" and a given amount locked for "Nay". To use `Split`, you'll have to specify the following:
- `aye` - the balance to lock for an "Aye" vote
- `nay` - the balance to lock for a "Nay" vote
- `SplitAbstain` - votes a split abstained vote, with a given amount locked for "Aye", a given amount locked for "Nay", and a given amount locked for an abstain vote (support). To use `SplitAbstain`, you'll have to specify the following:
- `aye` - the balance to lock for an "Aye" vote
- `nay` - the balance to lock for a "Nay" vote
- `abstain` - the balance to lock for an abstain vote
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const pollIndex = INSERT_REFERENDUM_INDEX;
const vote = INSERT_VOTE;
/*
For Standard, use the following format:
const vote = {
Standard: {
Vote: { aye: INSERT_BOOLEAN, conviction: INSERT_CONVICTION },
balance: INSERT_BALANCE,
},
};
For Split, use the following format:
const vote = {
Split: {
aye: INSERT_BALANCE,
nay: INSERT_BALANCE,
},
};
For SplitAbstrain, use the following format:
const vote = {
SplitAbstain: {
aye: INSERT_BALANCE,
nay: INSERT_BALANCE,
abstain: INSERT_BALANCE,
},
};
*/
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.convictionVoting.vote(pollIndex, vote);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
### Storage Methods {: #storage-methods }
The Conviction Voting Pallet includes the following read-only storage methods to obtain chain state data:
??? function "**classLocksFor**(account) - returns the voting classes (Origins and, by extension, Tracks), which have a non-zero lock requirement, and the lock amounts that they require"
=== "Parameters"
- `account` - the account to get voting information for
=== "Returns"
An array containing the class locks. Each class lock is an array that includes the index of the class (Origin and, by extension, Track) and the balance the voter has locked in the class. The index for each Track is as follows:
- `0` - Root Track
- `1` - Whitelisted Track
- `2` - General Admin Track
- `3` - Emergency Canceller Track
- `4` - Emergency Killer Track
```js
// If using Polkadot.js API and calling toJSON() on the query results
[
[
2, // Index of the class
'0x00000000000000000de0b6b3a7640000' // Amount locked
]
]
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const account = INSERT_ADDRESS;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const classLocksFor = await api.query.convictionVoting.classLocksFor(account);
};
main();
```
??? function "**palletVersion**() - returns the current pallet version"
=== "Parameters"
None.
=== "Returns"
A number representing the current version of the pallet.
```js
// If using Polkadot.js API and calling toJSON() on the query results
0
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const palletVersion = await api.query.convictionVoting.palletVersion();
};
main();
```
??? function "**votingFor**(account, class) - returns all of the votes for a particular voter in a particular voting class (Origin and, by extension, Track)"
=== "Parameters"
- `account` - the account to get the voting information for
- `class` - the index of the voting class. The index for each Track is as follows:
- `0` - Root Track
- `1` - Whitelisted Track
- `2` - General Admin Track
- `3` - Emergency Canceller Track
- `4` - Emergency Killer Track
=== "Returns"
The voting information for the given voter. The voter can be either `casting`, if the voter isn't actively delegating, or `delegating`, if the user is actively delegating
The information for each type.
=== "Casting"
If the voter isn't actively delegating. If the voter was previously assigned as a delegate, any delegate votes will appear under `delegations`.
```js
{
casting: {
votes: [
[
0, // Track Index
{
standard: { // Vote type can be either Standard, Split, or SplitAbstain
vote: '0x81', // The vote (Aye or Nay) and the Conviction
balance: '0x0000000000001999c6880e003a480000' // Vote value
}
}
]
],
delegations: { // Delegate votes
votes: '0x000000000000000ad78ebc5ac6200000', // Total Conviction-weighted votes
capital: '0x00000000000000056bc75e2d63100000' // Total delegated amount
},
prior: [ // Locked votes. After unlocking votes, this will reset to [0, 0]
56328, // The block at which the delegated amount can be unlocked
'0x00000000000000056bc75e2d63100000' // The delegated amount
]
}
}
```
=== "Delegating"
If the voter is actively delegating their votes to another voter. If the voter was previously delegated by another voter, their votes will appear under `delegations`.
```js
// If using Polkadot.js API and calling toJSON() on the query results
{
delegating: {
balance: '0x00000000000000056bc75e2d63100000', // The delegated amount
target: '0x3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0', // The delegate account
conviction: 'Locked2x', // The permitted Conviction
delegations: { // Delegate votes (if voter was previously delegated)
votes: 0, // Total Conviction-weighted votes
capital: 0 // Total delegated amount
},
prior: [ // Locked votes
0, // The block at which the delegated amount can be unlocked
0 // The delegated amount
]
}
}
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const account = INSERT_ADDRESS;
const classIndex = INSERT_TRACK_INDEX;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const votingFor = await api.query.convictionVoting.votingFor(
account,
classIndex
);
};
main();
```
### Pallet Constants {: #constants }
The Conviction Voting Pallet includes the following read-only functions to obtain pallet constants:
??? function "**maxVotes**() - returns the maximum number of concurrent votes an account may have"
=== "Parameters"
None.
=== "Returns"
The maximum number of votes.
```js
// If using Polkadot.js API and calling toJSON() on the result
20
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const maxVotes = api.consts.convictionVoting.maxVotes;
};
main();
```
??? function "**voteLockingPeriod**() - returns the minimum period of vote locking. It should not be shorter than the Enactment Period to ensure that, in the case of an approval, those successful voters are locked into the consequences that their votes entail"
=== "Parameters"
None.
=== "Returns"
The vote-locking period.
```js
// If using Polkadot.js API and calling toJSON() on the result
7200
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const voteLockingPeriod = api.consts.convictionVoting.voteLockingPeriod;
};
main();
```
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/substrate/interfaces/features/governance/parameters/
--- BEGIN CONTENT ---
---
title: Parameters Pallet
description: Learn how Moonbeam's Parameters Pallet safely and dynamically modifies network config items via on-chain governance, removing the need for runtime upgrades.
categories: Substrate Toolkit
---
# The Parameters Pallet
## Introduction {: #introduction }
The Parameters Pallet on Moonbeam is a governance-focused module that enables community-driven modifications to key network configuration items, such as the deposit requirement for the randomness module, directly on-chain through proposals and votes, without necessarily requiring a runtime upgrade. By removing the need for frequent code changes, the Parameters Pallet allows the network to respond more quickly to evolving needs while maintaining transparency and consensus.
This guide will provide an overview of the extrinsics, storage methods, and getters for the pallet constants available in the Parameters Pallet on Moonbeam. This guide assumes you are familiar with governance-related terminology; if not, please check out the [governance overview page](/learn/features/governance/#opengov){target=_blank} for more information.
## Parameters Pallet Interface {: #parameter-pallet-interface }
### Extrinsics {: #extrinsics }
The Parameters Pallet provides one extrinsic (function):
???+ function "**setParameter**(keyValue) - sets the value of a parameter"
=== "Parameters"
- `keyValue` - the key to the storage item to be modified
=== "Example"
Suppose you want to adjust the deposit parameter for the randomness pallet. You'd start by crafting a call to the `setParameter` function, specifying the randomness pallet's key and the new deposit value. In Polkadot.js Apps, this involves selecting `parameters.setParameter(keyValue)` and then updating the deposit field for `PalletRandomness`. While you can generate and review this call data beforehand, the actual change must still go through the [governance process](/learn/features/governance/#roadmap-of-a-proposal-v2){target=\_blank}—meaning it needs to be proposed, voted on, and approved by the community before the new deposit value takes effect on-chain
=== "Polkadot.js API Example"
```js
// This is an example of crafting the encoded call data via the Polkadot API
// but remember you won't submit the call here as it needs to go thru governance.
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Replace with your node's WSS endpoint
const provider = new WsProvider('INSERT_WSS_ENDPOINT');
const api = await ApiPromise.create({ provider });
// Construct the setParameter call for changing the randomness deposit
// Keep in mind that actual submission must go through governance (proposal, voting, etc.)
const tx = api.tx.parameters.setParameter({
PalletRandomness: {
// The deposit parameter is declared as a tuple: (variant, Option).
// Here we're setting the deposit to 5 tokens (5000000000000000000),
// e.g., 'MoonbaseRuntimeRuntimeParamsDynamicParamsPalletRandomnessDeposit' is the variant,
// and the second element is the actual deposit value in the Option.
Deposit: [
'MoonbaseRuntimeRuntimeParamsDynamicParamsPalletRandomnessDeposit',
'5000000000000000000',
],
},
});
// Print out the call in hex format (useful for creating a governance proposal)
console.log('Encoded call data:', tx.toHex());
await api.disconnect();
};
main();
```
### Storage Methods {: #storage-methods }
The Parameters Pallet includes the following read-only storage methods to obtain chain state data:
???+ function "**parameters**(parameters) - when queried with a parameter key, it returns either the corresponding value variant (e.g., `RuntimeConfig` with `FeesTreasuryProportion`) or `None` if no value is set"
=== "Parameters"
- `parameters` - the name of the pallet combined with the specific key identifying the storage item to retrieve
=== "Returns"
The `parameters` storage method is a dictionary that stores dynamic runtime parameters under specific keys. When queried with a parameter key, it returns either the corresponding value variant (e.g., `RuntimeConfig` with `FeesTreasuryProportion`) or `None` if no value is set
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Replace with the appropriate WebSocket endpoint
const provider = new WsProvider('INSERT_WSS_ENDPOINT');
const api = await ApiPromise.create({ provider });
// Define the parameter key
const paramKey = {
RuntimeConfig: 'FeesTreasuryProportion',
};
// Query the storage
const currentValue = await api.query.parameters.parameters(paramKey);
if (currentValue.isSome) {
const unwrapped = currentValue.unwrap();
console.log('Unwrapped value (toHuman):', unwrapped.toHuman());
console.log('Unwrapped value (toJSON):', unwrapped.toJSON());
} else {
console.log('None. No value stored for the given key.');
}
// Disconnect once done
await api.disconnect();
};
main();
```
??? function "**palletVersion**() - returns the current pallet version"
=== "Parameters"
None
=== "Returns"
A number representing the current version of the pallet
```js
// If using Polkadot.js API and calling toJSON() on the query results
0
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const palletVersion = await api.query.parameters.palletVersion();
console.log('The palletVersion is ' + palletVersion);
};
main();
```
### Pallet Constants {: #constants }
The Parameters Pallet does not have any constants.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/substrate/interfaces/features/governance/preimage/
--- BEGIN CONTENT ---
---
title: Preimage Pallet
description: Learn about the available extrinsics and storage methods for the Preimage Pallet on Moonbeam, which are used to store and manage on-chain preimages.
keywords: democracy, substrate, pallet, moonbeam, polkadot, preimage
categories: Substrate Toolkit
---
# The Preimage Pallet
## Introduction {: #introduction }
The Preimage Pallet allows users and the runtime to store the preimage of some encoded call data on chain. Furthermore, other pallets can use preimage hashes to store and manage large byte-blobs. For example, token holders can submit a governance proposal through the Referenda Pallet using a preimage hash of the action to be carried out.
Governance-related functionality is based on three new pallets and precompiles: the [Preimage Pallet](/builders/substrate/interfaces/features/governance/preimage/){target=\_blank} and [Preimage Precompile](/builders/ethereum/precompiles/features/governance/preimage/){target=\_blank}, the [Referenda Pallet](/builders/substrate/interfaces/features/governance/referenda/){target=\_blank} and [Referenda Precompile](/builders/ethereum/precompiles/features/governance/referenda/){target=\_blank}, and the [Conviction Voting Pallet](/builders/substrate/interfaces/features/governance/conviction-voting/){target=\_blank} and [Conviction Voting Precompile](/builders/ethereum/precompiles/features/governance/conviction-voting/){target=\_blank}. The aforementioned precompiles are Solidity interfaces that enable you to perform governance functions using the Ethereum API.
This guide will provide an overview of the extrinsics, storage methods, and getters for the pallet constants available in the Preimage Pallet on Moonbeam. This guide assumes you are familiar with governance-related terminology; if not, please check out the [governance overview page](/learn/features/governance/#opengov){target=_blank} for more information.
## Preimage Pallet Interface {: #preimage-pallet-interface }
### Extrinsics {: #extrinsics }
The Preimage Pallet provides the following extrinsics (functions):
??? function "**notePreimage**(encodedProposal) - registers a preimage for an upcoming proposal, given the encoded preimage of a proposal. If the preimage was previously requested, no fees or deposits are taken for providing the preimage. Otherwise, a deposit is taken proportional to the size of the preimage. Emits a `Noted` event"
=== "Parameters"
- `encodedProposal` - the encoded call data of the action that is being proposed. Please refer to the [How to Generate the Encoded Proposal](#generate-encoded-proposal) section for more information
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const encodedProposal = INSERT_ENCODED_PROPOSAL;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.preimage.notePreimage(encodedProposal);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**requestPreimage**(bytes) - requests a preimage to be uploaded to the chain without paying any fees or deposits. Once the preimage request has been submitted on-chain, the user who submitted the preimage and deposit will get their deposit back, and they will no longer control the preimage. Must be executed by the Root Origin. Emits a `Requested` event"
=== "Parameters"
- `bytes` - the hash of a preimage
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const bytes = INSERT_PREIMAGE_HASH;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.preimage.requestPreimage(bytes);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**unnotePreimage**(hash) - clears an unrequested preimage from the runtime storage, given the hash of the preimage to be removed. Emits a `Cleared` event"
=== "Parameters"
- `hash` - the hash of a preimage
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const hash = INSERT_PREIMAGE_HASH;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.preimage.unnotePreimage(hash);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**unrequestPreimage**(hash) - clears a previously made request for a preimage. Must be executed by the Root Origin. Emits a `Cleared` event"
=== "Parameters"
- `hash` - the hash of a preimage
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const hash = INSERT_PREIMAGE_HASH;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.preimage.unrequestPreimage(hash);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
### Storage Methods {: #storage-methods }
The Preimage Pallet includes the following read-only storage methods to obtain chain state data:
??? function "**palletVersion**() - returns the current pallet version"
=== "Parameters"
None.
=== "Returns"
A number representing the current version of the pallet.
```js
// If using Polkadot.js API and calling toJSON() on the query results
0
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const palletVersion = await api.query.preimage.palletVersion();
};
main();
```
??? function "**preimageFor**([hash, length]) - returns the encoded proposal for a preimage, given the hash and length of the preimage"
=== "Parameters"
- `[hash, length]` - a tuple containing the hash and the length of the preimage
=== "Returns"
The encoded call data of the proposal.
```js
// If using Polkadot.js API and calling toJSON() on the query results
0x00002c68656c6c6f5f776f726c64
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const preimageInfo = [INSERT_PREIMAGE_HASH, INSERT_PREIMAGE_LENGTH];
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const preimageFor = await api.query.preimage.preimageFor(preimageInfo);
};
main();
```
??? function "**statusFor**(hash) - returns the request status for a given preimage hash"
=== "Parameters"
- `hash` - the preimage hash to get the request status for
=== "Returns"
Status information for the preimage, which includes the status, the preimage deposit information, and the length of the preimage. The status can be either `unrequested` or `requested`.
```js
{
unrequested: { // Request status
deposit: [
'0x3B939FeaD1557C741Ff06492FD0127bd287A421e', // Depositor
'0x00000000000000004569f6996d8c8000' // Amount deposited
],
len: 18 // Length of the preimage
}
}
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const hash = INSERT_PREIMAGE_HASH;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const statusFor = await api.query.preimage.statusFor(hash);
};
main();
```
## How to Generate an Encoded Proposal {: #generate-encoded-proposal }
To generate an encoded proposal, you must first create the extrinsic that will be run if the proposal passes the governance process. Instead of attempting to send the extrinsic, you'll obtain the SCALE-encoded hash of the extrinsic, which you'll use to submit the preimage.
For example, if you wanted to set an on-chain remark that said "Hello World," you could generate the encoded call data using the following snippet:
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('ws://127.0.0.1:9944'),
});
const encodedProposal = api.tx.system.remark('Hello World').method.toHex();
api.disconnect();
};
main();
```
Then, you can use the encoded call data to submit the preimage for the proposal:
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const encodedProposal = api.tx.system.remark('Hello World').method.toHex();
const tx = api.tx.preimage.notePreimage(encodedProposal);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/substrate/interfaces/features/governance/referenda/
--- BEGIN CONTENT ---
---
title: Referenda Pallet
description: This guide covers the available functions for the Referenda Pallet on Moonbeam, of which are used to view and submit data related to on-chain referenda
keywords: democracy, substrate, pallet, moonbeam, polkadot, voting, vote, referenda
categories: Substrate Toolkit
---
# The Referenda Pallet
## Introduction {: #introduction }
The Referenda Pallet allows token holders to make, delegate, and manage Conviction-weighted votes on referenda.
Governance-related functionality is based on three new pallets and precompiles: the [Preimage Pallet](/builders/substrate/interfaces/features/governance/preimage/){target=\_blank} and [Preimage Precompile](/builders/ethereum/precompiles/features/governance/preimage/){target=\_blank}, the [Referenda Pallet](/builders/substrate/interfaces/features/governance/referenda/){target=\_blank} and [Referenda Precompile](/builders/ethereum/precompiles/features/governance/referenda/){target=\_blank}, and the [Conviction Voting Pallet](/builders/substrate/interfaces/features/governance/conviction-voting/){target=\_blank} and [Conviction Voting Precompile](/builders/ethereum/precompiles/features/governance/conviction-voting/){target=\_blank}. The aforementioned precompiles are Solidity interfaces that enable you to perform governance functions using the Ethereum API.
This guide will provide an overview of the extrinsics, storage methods, and getters for the pallet constants available in the Referenda Pallet on Moonbeam. This guide assumes you are familiar with governance-related terminology, if not, please check out the [governance overview page](/learn/features/governance/#opengov){target=\_blank} for more information.
## Referenda Pallet Interface {: #referenda-pallet-interface }
### Extrinsics {: #extrinsics }
The Referenda Pallet provides the following extrinsics (functions):
??? function "**cancel**(index) - cancels an ongoing referendum given the index of the referendum to cancel. This type of action requires a proposal to be created and assigned to either the Root Track or the Emergency Canceller Track"
=== "Parameters"
- `index` - the index of the referendum to cancel
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const index = INSERT_REFERENDUM_INDEX;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.referenda.cancel(index);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**kill**(index) - cancels an ongoing referendum and slashes the deposits given the index of the referendum to cancel. This type of action requires a proposal to be created and assigned to either the Root Track or the Emergency Killer Track"
=== "Parameters"
- `index` - the index of the referendum to kill
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const index = INSERT_REFERENDUM_INDEX;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.referenda.kill(index);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**placeDecisionDeposit**(index) - posts the Decision Deposit for a referendum, given the index of the referendum"
=== "Parameters"
- `index` - the index of the referendum to place the Decision Deposit for
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const index = INSERT_REFERENDUM_INDEX;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.referenda.placeDecisionDeposit(index);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**refundDecisionDeposit**(index) - refunds the Decision Deposit for a closed referendum back to the depositor, given the index of the referendum"
=== "Parameters"
- `index` - the index of the referendum to refund the Decision Deposit for
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const index = INSERT_REFERENDUM_INDEX;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.referenda.refundDecisionDeposit(index);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**refundSubmissionDeposit**(index) - refunds the Submission Deposit for a closed referendum back to the depositor, given the index of the referendum"
=== "Parameters"
- `index` - the index of the referendum to refund the Submission Deposit for
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const index = INSERT_REFERENDUM_INDEX;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.referenda.refundSubmissionDeposit(index);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**submit**(proposalOrigin, proposal, enactmentMoment) - proposes a referendum on a privileged action given the Origin from which the proposal should be executed, the proposal, and the moment that the proposal should be enacted"
=== "Parameters"
- `proposalOrigin` - the Origin and, by extension, the Track from which the proposal should be executed. Typically, this should be set to one of the following:
- `system` - indicates the proposal should be executed by a system-level Origin. You can specify the name of the Origin or the index associated with the Origin:
- `Root` or `0` - submits a proposal to the Root Track
- `Origins` - indicates the proposal should be executed by one of the governance Origins. To submit a proposal to any of the Tracks aside from Root, you can specify the name of the Origin or the index associated with the Origin:
- `WhitelistedCaller` or `0` - submits a proposal to the Whitelisted Track
- `GeneralAdmin` or `1` - submits a proposal to the General Admin Track
- `ReferendumCanceller` or `2` - submits a proposal to the Emergency Canceller Track
- `ReferendumKiller` or `3` - submits a proposal to the Emergency Killer Track
- `proposal` - the action being proposed. To define the proposal to submit, you can use the following method:
- `Lookup` - defines the preimage associated with the proposal using the following arguments:
- `hash_` - the hash of the preimage
- `len` - the length of the preimage
- `enactmentMoment` - when the proposal will be executed, either at a specific block or after a specific number of blocks:
- `At` - a specific block to enact the proposal at
- `After` - the number of blocks to delay enactment after proposal approval
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const proposalOrigin = INSERT_PROPOSAL_ORIGIN;
/*
For Root Origin, use the following format:
const proposalOrigin = { system: 'Root' };
For all other OpenGov Origins, use the following format:
const proposalOrigin = { Origins: 'INSERT_ORIGIN_NAME_OR_INDEX' };
*/
const proposal = {
Lookup: {
hash_: 'INSERT_PREIMAGE_HASH',
len: 'INSERT_PREIMAGE_LENGTH',
},
};
const enactmentMoment = { At: INSERT_BLOCK };
/*
Or for After, use the following:
const enactmentMoment = { After: INSERT_BLOCK }
*/
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.referenda.submit(proposalOrigin, proposal, enactmentMoment);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
### Storage Methods {: #storage-methods }
The Referenda Pallet includes the following read-only storage methods to obtain chain state data:
??? function "**decidingCount**(index) - returns the number of referenda being decided currently"
=== "Parameters"
- `index` - the index of the Track to get the deciding count for. The index for each Track is as follows:
- `0` - Root Track
- `1` - Whitelisted Track
- `2` - General Admin Track
- `3` - Emergency Canceller Track
- `4` - Emergency Killer Track
=== "Returns"
The number of referenda currently being decided on for the given Track.
```js
// If using Polkadot.js API and calling toJSON() on the query results
1
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const track = INSERT_TRACK_INDEX;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const statusFor = await api.query.referenda.decidingCount(track);
};
main();
```
??? function "**palletVersion**() - returns the current pallet version"
=== "Parameters"
None.
=== "Returns"
A number representing the current version of the pallet.
```js
// If using Polkadot.js API and calling toJSON() on the query results
0
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const palletVersion = await api.query.referenda.palletVersion();
};
main();
```
??? function "**referendumCount**() - returns the number of referenda started so far"
=== "Parameters"
None.
=== "Returns"
The number of referenda started so far.
```js
// If using Polkadot.js API and calling toJSON() on the query results
1
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const statusFor = await api.query.referenda.referendumCount();
};
main();
```
??? function "**referendumInfoFor**(index) - returns information concerning any given referendum"
=== "Parameters"
- `index` - the index of the referendum to get the information for
=== "Returns"
The status of the referendum and additional information depending on the status. The status can be any of the following:
=== "Ongoing"
The referendum has been submitted and is being voted on. The returned data includes information on the proposal, the deposits, the current state of the referendum, and more.
```js
// If using Polkadot.js API and calling toJSON() on the query results
{
ongoing: {
track: 2,
origin: { origins: 'GeneralAdmin' },
proposal: {
lookup: {
hash: '0xa5d90079f950888dabb2ef77e159096701784141dd2c8c95a67ced96ec0c1c21',
len: 15
}
},
enactment: { after: 100 },
submitted: 5724140,
submissionDeposit: {
who: '0xD720165D294224A7d16F22ffc6320eb31f3006e1',
amount: '0x00000000000000008ac7230489e80000'
},
decisionDeposit: {
who: '0xD720165D294224A7d16F22ffc6320eb31f3006e1',
amount: '0x000000000000001b1ae4d6e2ef500000'
},
deciding: { since: 5724440, confirming: null },
tally: { ayes: 0, nays: 0, support: 0 },
inQueue: false,
alarm: [ 5825240, [ 5825240, 0 ] ]
}
}
```
=== "Approved"
The referendum finished with approval. The returned data includes the block at which the proposal was approved and deposit information, including the account(s) that placed a deposit and the deposit amount for that account.
```js
// If using Polkadot.js API and calling toJSON() on the query results
{
approved: [
3715966, // Block at which the proposal was approved
{ // Deposit information
who: '0xE6c5B9500035cb5557E8FDBAa758d78a15361A0E',
amount: '0x00000000000000056bc75e2d63100000'
},
null // Additional deposit information or null if there isn't any
]
}
```
=== "Rejected"
The referendum ended with a rejection. The returned data includes the block at which the proposal was rejected and deposit information, including the account(s) that placed a deposit and the deposit amount for that account.
```js
// If using Polkadot.js API and calling toJSON() on the query results
{
rejected: [
5213165, // Block at which the proposal was rejected
{ // Deposit information
who: '0xb926E36D439106090Be1151347CFB916E44AFE00',
amount: '0x00000000000000008ac7230489e80000'
},
null // Additional deposit information or null if there isn't any
]
}
```
=== "Cancelled"
The referendum ended with a cancellation. The returned data includes the block at which the proposal was cancelled and deposit information, including the account(s) that placed a deposit and the deposit amount for that account.
```js
// If using Polkadot.js API and calling toJSON() on the query results
{
cancelled: [
3613947, // Block at which the proposal was cancelled
{ // Deposit information
who: '0xE6c5B9500035cb5557E8FDBAa758d78a15361A0E',
amount: '0x00000000000000056bc75e2d63100000'
},
null // Additional deposit information or null if there isn't any
]
}
```
=== "Timed Out"
The referendum ended and was never decided. The returned data includes the block at which the proposal timed out and deposit information, including the account(s) that placed a deposit and the deposit amount for that account.
```js
// If using Polkadot.js API and calling toJSON() on the query results
{
timedOut: [
4585127, // Block at which the proposal timed out
{ // Deposit information
who: '0x657a901AFC4d85A28eEf0F6696E42ae2099219cd',
amount: '0x00000000000000008ac7230489e80000'
},
null // Additional deposit information or null if there isn't any
]
}
```
=== "Killed"
The referendum ended with a kill. The block at which the referendum was killed is returned.
```js
// If using Polkadot.js API and calling toJSON() on the query results
{ killed: 1806494 } // The block at which the referendum was killed
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const index = INSERT_REFERENDUM_INDEX;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const referendumInfoFor = await api.query.referenda.referendumInfoFor(index);
};
main();
```
??? function "**trackQueue**(index) - returns the sorted list of referenda ready to be decided but not yet being decided on for a given Track. The referenda are sorted by Conviction-weighted approvals"
=== "Parameters"
- `index` - the index of the Track to get the queue information for. The index for each Track is as follows:
- `0` - Root Track
- `1` - Whitelisted Track
- `2` - General Admin Track
- `3` - Emergency Canceller Track
- `4` - Emergency Killer Track
=== "Returns"
The list of referenda queued for a given Track. This should return an empty array if the deciding count is less than the maximum number of referenda that can be decided on.
```js
// If using Polkadot.js API and calling toJSON() on the query results
[
[
5, // Referendum Index
0 // Track Index
]
]
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const index = INSERT_TRACK_INDEX;
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const trackQueue = await api.query.referenda.trackQueue(index);
};
main();
```
### Pallet Constants {: #constants }
The Referenda Pallet includes the following read-only functions to obtain pallet constants:
??? function "**maxQueued**() - returns the maximum size of the referendum queue for a single Track"
=== "Parameters"
None.
=== "Returns"
The maximum number of queued referenda for a single Track.
```js
// If using Polkadot.js API and calling toJSON() on the query results
100
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const maxQueued = api.consts.referenda.maxQueued;
};
main();
```
??? function "**submissionDeposit**() - returns the minimum amount to be used as a deposit for a public referendum proposal"
=== "Parameters"
None.
=== "Returns"
The minimum amount required for the Submission Deposit.
```js
// If using Polkadot.js API and calling toJSON() on the query results
0x00000000000000008ac7230489e80000
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const submissionDeposit = api.consts.referenda.submissionDeposit;
};
main();
```
??? function "**tracks**() - returns information concerning the different referendum Tracks"
=== "Parameters"
None.
=== "Returns"
Information on each Track. This includes [general](/learn/features/governance#general-parameters-by-track){target=_blank}, [period](/learn/features/governance#period-parameters-by-track){target=_blank}, and [Approval and Support](/learn/features/governance#support-and-approval-parameters-by-track){target=_blank} parameters.
```js
// If using Polkadot.js API and calling toJSON() on the query results
[
[
0, // Track Index
{
name: 'root',
maxDeciding: 5,
decisionDeposit: '0x000000000000152d02c7e14af6800000',
preparePeriod: 7200,
decisionPeriod: 100800,
confirmPeriod: 7200,
minEnactmentPeriod: 7200,
minApproval: {
reciprocal: { factor: 999999999, xOffset: 999999999, yOffset: 0 }
},
minSupport: {
linearDecreasing: { length: 1000000000, floor: 5000000, ceil: 250000000 }
}
}
],
[
1,
{
name: 'whitelisted_caller',
maxDeciding: 100,
decisionDeposit: '0x000000000000021e19e0c9bab2400000',
preparePeriod: 50,
decisionPeriod: 100800,
confirmPeriod: 50,
minEnactmentPeriod: 150,
minApproval: {
reciprocal: { factor: 999999999, xOffset: 999999999, yOffset: 0 }
},
minSupport: {
reciprocal: { factor: 60061, xOffset: 2994150, yOffset: -59882 }
}
}
],
[
2,
{
name: 'general_admin',
maxDeciding: 10,
decisionDeposit: '0x000000000000001b1ae4d6e2ef500000',
preparePeriod: 300,
decisionPeriod: 100800,
confirmPeriod: 7200,
minEnactmentPeriod: 7200,
minApproval: {
reciprocal: { factor: 999999999, xOffset: 999999999, yOffset: 0 }
},
minSupport: {
reciprocal: { factor: 222222224, xOffset: 333333335, yOffset: -166666668 }
}
}
],
[
3,
{
name: 'referendum_canceller',
maxDeciding: 20,
decisionDeposit: '0x000000000000021e19e0c9bab2400000',
preparePeriod: 300,
decisionPeriod: 100800,
confirmPeriod: 900,
minEnactmentPeriod: 50,
minApproval: {
reciprocal: { factor: 999999999, xOffset: 999999999, yOffset: 0 }
},
minSupport: {
reciprocal: { factor: 787400, xOffset: 1572327, yOffset: -786164 }
}
}
],
[
4,
{
name: 'referendum_killer',
maxDeciding: 100,
decisionDeposit: '0x000000000000043c33c1937564800000',
preparePeriod: 300,
decisionPeriod: 100800,
confirmPeriod: 900,
minEnactmentPeriod: 50,
minApproval: {
reciprocal: { factor: 999999999, xOffset: 999999999, yOffset: 0 }
},
minSupport: {
reciprocal: { factor: 869501, xOffset: 8620680, yOffset: -862069 }
}
}
]
]
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tracks = api.consts.referenda.tracks;
};
main();
```
??? function "**undecidingTimeout**() - the number of blocks after submission that a referendum must begin being decided by. Once this passes, then anyone may cancel the referendum"
=== "Parameters"
None.
=== "Returns"
The number of blocks before a timeout occurs.
```js
// If using Polkadot.js API and calling toJSON() on the query results
151200
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const undecidingTimeout = api.consts.referenda.undecidingTimeout;
};
main();
```
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/substrate/interfaces/features/randomness/
--- BEGIN CONTENT ---
---
title: Randomness Pallet
description: Learn about the available extrinsics, storage methods, and constants in the Randomness Pallet on Moonbeam to retrieve data on randomness requests and results.
keywords: randomness, VRF, substrate, pallet, moonbeam, polkadot
categories: Substrate Toolkit
---
# The Randomness Pallet
## Introduction {: #introduction }
Moonbeam utilizes verifiable random functions (VRF) to generate randomness that can be verified on-chain. A VRF is a cryptographic function that takes some input and produces random values, along with a proof of authenticity that these random values were generated by the submitter. The proof can be verified by anyone to ensure the random values generated were calculated correctly. For more information on Moonbeam's on-chain randomness, such as an overview on the randomness sources, the request and fulfill cycle, and more, please refer to the [Randomness on Moonbeam](/learn/features/randomness/){target=\_blank} overview page.
The randomness pallet enables you to check on randomness requests that have not been fulfilled or purged, randomness results, and more. To actually request and fulfill randomness, you can use the randomness precompile and randomness consumer contracts. The precompile is a Solidity interface that enables you to request randomness, check on the status of requests, fulfill requests, and more through the Ethereum API. For more information on how to use both of these contracts, please refer to the [Randomness Precompile](/builders/ethereum/precompiles/features/randomness/){target=\_blank} guide.
This page will provide an overview of the storage methods and getters for the pallet constants available in the randomness pallet.
## Randomness Pallet Interface {: #randomness-pallet-interface }
### Storage Methods {: #storage-methods }
The randomness pallet includes the following read-only storage methods to obtain chain state data:
??? function "**localVrfOutput**() - returns the current local per-block VRF randomness"
=== "Parameters"
None
=== "Returns"
`H256` - A 32-byte (256-bit) hex value, starting with "0x"`
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the local VRF output from randomness pallet
const localVrf = await api.query.randomness.localVrfOutput();
console.log('Local VRF Output:', localVrf.toString());
process.exit(0);
} catch (error) {
console.error('Error querying local VRF output:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**palletVersion**() - returns the current pallet version"
=== "Parameters"
None
=== "Returns"
`u16` - The pallet version
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the pallet version from randomness pallet
const version = await api.query.randomness.palletVersion();
console.log('Randomness Pallet Version:', version.toString());
process.exit(0);
} catch (error) {
console.error('Error querying randomness pallet version:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**randomnessResults**(PalletRandomnessRequestType) - snapshot of randomness to fulfill all requests that are for the same raw randomness"
=== "Parameters"
- `PalletRandomnessRequestType` - You can optionally provide the type of randomness you'd like, e.g. `Local` or `BabeEpoch` Randomness. If you omit this, you'll receive all types of randomness.
=== "Returns"
The query returns mappings of request types to their randomness outcomes, where:
1. Key: Identifies the source and timing of the randomness request. e.g. `{ Local: '4,619,640' }` indicates this was a Local randomness request from block number 4,619,640. The Local type uses block numbers as identifiers, while BabeEpoch uses epoch numbers.
2. Value: Contains two pieces of information, including `randomness`: A 32-byte hex string (0x15b5f6...c816) representing the random value generated and `requestCount`: The number of requests that used this same random value (e.g. '1')
Multiple requests for randomness at the same block/epoch would share the same random value, which is why there's a requestCount field.
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Query Babe Epoch randomness results
const babeResults = await api.query.randomness.randomnessResults({
BabeEpoch: 0,
});
console.log('\nBabe Epoch Randomness Results:');
console.log(babeResults.toHuman());
// Query Local randomness results
const localResults = await api.query.randomness.randomnessResults({
Local: 0,
});
console.log('\nLocal Randomness Results:');
console.log(localResults.toHuman());
// Get the available keys/entries
console.log('\nAll Available Randomness Results:');
const entries = await api.query.randomness.randomnessResults.entries();
entries.forEach(([key, value]) => {
console.log(
'Key:',
key.args.map((k) => k.toHuman())
);
console.log('Value:', value.toHuman());
console.log('---');
});
process.exit(0);
} catch (error) {
console.error('Error querying randomness results:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**relayEpoch**() - returns the relay epoch"
=== "Parameters"
None
=== "Returns"
`u64` - the relay epoch
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the relay epoch
const relayEpoch = await api.query.randomness.relayEpoch();
console.log('Current Relay Epoch:', relayEpoch.toString());
process.exit(0);
} catch (error) {
console.error('Error querying relay epoch:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**requestCount**() - returns the number of randomness requests made so far, and is used to generate the next request's uid"
=== "Parameters"
None
=== "Returns"
`u64` - the request count
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the request count
const requestCount = await api.query.randomness.requestCount();
console.log('Total Randomness Requests:', requestCount.toString());
console.log(
'Next Request UID will be:',
(Number(requestCount) + 1).toString()
);
process.exit(0);
} catch (error) {
console.error('Error querying request count:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**requests**(u64) - returns a given randomness request or all of the randomness requests that have not been fulfilled nor purged yet"
=== "Parameters"
- `u64` - The request ID number (optional)
=== "Returns"
Returns an Option containing the request information if it exists and hasn't been fulfilled/purged, including:
- The request type (Local or Babe)
- When it can be fulfilled
- Number of random words requested
- The requester's information
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// First get the current request count
const requestCount = await api.query.randomness.requestCount();
console.log('Total Request Count:', requestCount.toString());
// Query most recent request as an example
if (requestCount > 0) {
const latestRequestId = requestCount - 1;
const specificRequest =
await api.query.randomness.requests(latestRequestId);
console.log('\nLatest Request (ID:', latestRequestId.toString(), '):');
if (specificRequest.isSome) {
console.log(specificRequest.unwrap().toHuman());
} else {
console.log('Request has been fulfilled or purged');
}
}
// Query all available requests
console.log('\nAll Pending Requests:');
const allRequests = await api.query.randomness.requests.entries();
if (allRequests.length === 0) {
console.log('No pending requests found');
} else {
allRequests.forEach(([key, value]) => {
const requestId = key.args[0].toString();
console.log('\nRequest ID:', requestId);
if (value.isSome) {
const request = value.unwrap();
console.log('Request Details:', request.toHuman());
}
});
// Show some statistics
console.log('\nRequest Statistics:');
console.log('Total Pending Requests:', allRequests.length);
}
process.exit(0);
} catch (error) {
console.error('Error querying randomness requests:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
### Pallet Constants {: #constants }
The randomness pallet includes the following read-only functions to obtain pallet constants:
??? function "**blockExpirationDelay**() - the number of blocks that must pass before a local VRF request expires and can be purged"
=== "Parameters"
None
=== "Returns"
`u32` - the number of blocks that must pass before a local VRF request expires and can be purged
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the block expiration delay constant
const blockExpirationDelay =
await api.consts.randomness.blockExpirationDelay;
console.log(
'Block Expiration Delay:',
blockExpirationDelay.toString(),
'blocks'
);
process.exit(0);
} catch (error) {
console.error('Error querying block expiration delay:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**deposit**() - the amount that should be taken as a security deposit when requesting random words. There is one deposit per request"
=== "Parameters"
None
=== "Returns"
`u128` - the amount that should be taken as a security deposit when requesting random words
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the deposit constant
const deposit = await api.consts.randomness.deposit;
console.log('Randomness Request Deposit:', deposit.toString(), 'Wei');
console.log(
'Deposit in DEV:',
(BigInt(deposit) / BigInt(10 ** 18)).toString()
);
process.exit(0);
} catch (error) {
console.error('Error querying randomness deposit:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**epochExpirationDelay**() - the number of epochs that must pass before a BABE request expires and can be purged"
=== "Parameters"
None
=== "Returns"
`u64` - the number of epochs that must pass before a BABE request expires and can be purged
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the epoch expiration delay constant
const epochExpirationDelay =
await api.consts.randomness.epochExpirationDelay;
console.log(
'Epoch Expiration Delay:',
epochExpirationDelay.toString(),
'epochs'
);
process.exit(0);
} catch (error) {
console.error('Error querying epoch expiration delay:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**maxBlockDelay**() - the maximum number of blocks (after the block in which the request was made) that can pass before a local VRF request is fulfilled"
=== "Parameters"
None
=== "Returns"
`u32` - the maximum number of blocks that can pass before a local VRF request is fulfilled
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the maximum block delay constant
const maxBlockDelay = await api.consts.randomness.maxBlockDelay;
console.log('Maximum Block Delay:', maxBlockDelay.toString(), 'blocks');
process.exit(0);
} catch (error) {
console.error('Error querying max block delay:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**maxRandomWords**() - the maximum number of random words that can be requested"
=== "Parameters"
None
=== "Returns"
`u8` - the maximum number of random words that can be requested
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the maximum random words constant
const maxRandomWords = await api.consts.randomness.maxRandomWords;
console.log('Maximum Random Words:', maxRandomWords.toString(), 'words');
process.exit(0);
} catch (error) {
console.error('Error querying max random words:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**minBlockDelay**() - the minimum number of blocks (after the block in which the request was made) that must pass before a local VRF request can be fulfilled"
=== "Parameters"
None
=== "Returns"
`u32` - the minimum number of blocks (after the block in which the request was made) that must pass before a local VRF request can be fulfilled
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the minimum block delay constant
const minBlockDelay = await api.consts.randomness.minBlockDelay;
console.log('Minimum Block Delay:', minBlockDelay.toString(), 'blocks');
process.exit(0);
} catch (error) {
console.error('Error querying min block delay:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/substrate/interfaces/features/staking/
--- BEGIN CONTENT ---
---
title: Parachain Staking Pallet
description: Learn about the Parachain Staking Pallet interface on Moonbeam, which can be used to perform delegator and collator activities and retrieve staking information.
keywords: staking, substrate, pallet, moonbeam, polkadot
categories: Substrate Toolkit, Staking
---
# The Parachain Staking Pallet
## Introduction {: #introduction }
Moonbeam uses a Delegated Proof of Stake (DPoS) system that determines which collators are eligible to produce blocks based on their total stake in the network. For general information on staking, such as general terminology, staking variables, and more, please refer to the [Staking on Moonbeam](/learn/features/staking/){target=\_blank} page.
The DPoS system is powered by the [parachain staking](https://github.com/moonbeam-foundation/moonbeam/tree/master/pallets/parachain-staking/src){target=\_blank} pallet, allowing token holders (delegators) to express exactly which collator candidates they would like to support and with what quantity of stake. The design of the parachain staking pallet is such that it enforces shared risk/reward on chain between delegators and candidates.
Some of the functionality of the parachain staking pallet is also available through a staking precompile. The precompile is a Solidity interface that enables you to perform staking actions through the Ethereum API. Please refer to the [Staking Precompile](/builders/ethereum/precompiles/features/staking/){target=\_blank} guide for more information.
This guide will provide an overview of the extrinsics, storage methods, and getters for the pallet constants available in the parachain staking pallet.
## Exit Delays {: #exit-delays }
Some of the staking pallet extrinsics include exit delays that you must wait before the request can be executed. The exit delays to note are as follows:
=== "Moonbeam"
| Variable | Value |
|:-----------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------------------:|
| Decrease candidate bond | {{ networks.moonbeam.collator_timings.can_bond_less.rounds }} rounds ({{ networks.moonbeam.collator_timings.can_bond_less.hours }} hours) |
| Decrease delegator bond | {{ networks.moonbeam.delegator_timings.del_bond_less.rounds }} rounds ({{ networks.moonbeam.delegator_timings.del_bond_less.hours }} hours) |
| Revoke delegation | {{ networks.moonbeam.delegator_timings.revoke_delegations.rounds }} rounds ({{ networks.moonbeam.delegator_timings.revoke_delegations.hours }} hours) |
| Leave candidates | {{ networks.moonbeam.collator_timings.leave_candidates.rounds }} rounds ({{ networks.moonbeam.collator_timings.leave_candidates.hours }} hours) |
| Leave delegators | {{ networks.moonbeam.delegator_timings.leave_delegators.rounds }} rounds ({{ networks.moonbeam.delegator_timings.leave_delegators.hours }} hours) |
=== "Moonriver"
| Variable | Value |
|:-----------------------:|:-------------------------------------------------------------------------------------------------------------------------------------------------------:|
| Decrease candidate bond | {{ networks.moonriver.collator_timings.can_bond_less.rounds }} rounds ({{ networks.moonriver.collator_timings.can_bond_less.hours }} hours) |
| Decrease delegator bond | {{ networks.moonriver.delegator_timings.del_bond_less.rounds }} rounds ({{ networks.moonriver.delegator_timings.del_bond_less.hours }} hours) |
| Revoke delegation | {{ networks.moonriver.delegator_timings.revoke_delegations.rounds }} rounds ({{ networks.moonriver.delegator_timings.revoke_delegations.hours }} hours) |
| Leave candidates | {{ networks.moonriver.collator_timings.leave_candidates.rounds }} rounds ({{ networks.moonriver.collator_timings.leave_candidates.hours }} hours) |
| Leave delegators | {{ networks.moonriver.delegator_timings.leave_delegators.rounds }} rounds ({{ networks.moonriver.delegator_timings.leave_delegators.hours }} hours) |
=== "Moonbase Alpha"
| Variable | Value |
|:-----------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------------------:|
| Decrease candidate bond | {{ networks.moonbase.collator_timings.can_bond_less.rounds }} rounds ({{ networks.moonbase.collator_timings.can_bond_less.hours }} hours) |
| Decrease delegator bond | {{ networks.moonbase.delegator_timings.del_bond_less.rounds }} rounds ({{ networks.moonbase.delegator_timings.del_bond_less.hours }} hours) |
| Revoke delegation | {{ networks.moonbase.delegator_timings.revoke_delegations.rounds }} rounds ({{ networks.moonbase.delegator_timings.revoke_delegations.hours }} hours) |
| Leave candidates | {{ networks.moonbase.collator_timings.leave_candidates.rounds }} rounds ({{ networks.moonbase.collator_timings.leave_candidates.hours }} hours) |
| Leave delegators | {{ networks.moonbase.delegator_timings.leave_delegators.rounds }} rounds ({{ networks.moonbase.delegator_timings.leave_delegators.hours }} hours) |
## Parachain Staking Pallet Interface {: #parachain-staking-pallet-interface }
### Extrinsics {: #extrinsics }
The parachain staking pallet provides the following extrinsics (functions):
??? function "**cancelCandidateBondLess**() - cancels a pending scheduled request to decrease a candidate's self bond amount"
=== "Parameters"
None
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup account from private key
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const account = keyring.addFromUri(PRIVATE_KEY);
console.log('Account address:', account.address);
// Create the cancel transaction
const tx = api.tx.parachainStaking.cancelCandidateBondLess();
// Sign and send the transaction
await tx.signAndSend(account, ({ status, events }) => {
if (status.isInBlock) {
console.log(`Transaction included in block hash: ${status.asInBlock}`);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful cancellation
if (
section === 'parachainStaking' &&
method === 'CancelledCandidateBondLess'
) {
const [candidate, amount, executeRound] = data;
console.log('\nSuccessfully cancelled bond decrease request!');
console.log('Candidate:', candidate.toString());
console.log('Amount that was to be decreased:', amount.toString());
console.log(
'Round it was to be executed:',
executeRound.toString()
);
}
});
process.exit(0);
}
});
} catch (error) {
console.error('Error in cancelling candidate bond less:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**cancelDelegationRequest**(candidate) - cancels any pending delegation requests provided the address of a candidate"
=== "Parameters"
- `candidate` - The address of the relevant collator
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup delegator account from private key
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const delegator = keyring.addFromUri(PRIVATE_KEY);
// The candidate's address for which to cancel the delegation request
const candidateAddress = 'INSERT_COLLATOR_ADDRESS';
console.log('Delegator address:', delegator.address);
console.log('Candidate address:', candidateAddress);
// Create the cancel delegation request transaction
const tx =
api.tx.parachainStaking.cancelDelegationRequest(candidateAddress);
// Sign and send the transaction
await tx.signAndSend(delegator, ({ status, events }) => {
if (status.isInBlock) {
console.log(`Transaction included in block hash: ${status.asInBlock}`);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful cancellation
if (
section === 'parachainStaking' &&
method === 'CancelledDelegationRequest'
) {
const [delegatorAddress, scheduledRequest, candidateAddress] = data;
console.log('\nSuccessfully cancelled delegation request!');
console.log('Delegator:', delegatorAddress.toString());
console.log('Candidate:', candidateAddress.toString());
const request = scheduledRequest.toJSON();
console.log('Request details:');
console.log('- Execution round:', request.whenExecutable);
if (request.action.decrease) {
console.log('- Action: Decrease by', request.action.decrease);
} else if (request.action.revoke) {
console.log('- Action: Revoke amount', request.action.revoke);
}
}
});
process.exit(0);
}
});
} catch (error) {
console.error('Error in cancelling delegation request:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**cancelLeaveCandidates**(candidateCount) - cancels a candidate's pending scheduled request to leave the candidate pool given the current number of candidates in the pool"
=== "Parameters"
- `candidateCount` - The current number of collator candidates in the pool
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup candidate account from private key
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const candidate = keyring.addFromUri(PRIVATE_KEY);
// First, get the current candidate count from the chain
const candidates = await api.query.parachainStaking.candidatePool();
const candidateCount = candidates.length;
console.log('Candidate address:', candidate.address);
console.log('Current candidate count:', candidateCount);
// Create the cancel leave candidates transaction
const tx = api.tx.parachainStaking.cancelLeaveCandidates(candidateCount);
// Sign and send the transaction
await tx.signAndSend(candidate, ({ status, events }) => {
if (status.isInBlock) {
console.log(`Transaction included in block hash: ${status.asInBlock}`);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful cancellation
if (
section === 'parachainStaking' &&
method === 'CancelledLeaveCandidates'
) {
const [candidateAddress, candidateCount] = data;
console.log('\nSuccessfully cancelled leave candidates request!');
console.log('Candidate:', candidateAddress.toString());
console.log(
'Candidate count at cancellation:',
candidateCount.toString()
);
}
});
process.exit(0);
}
});
} catch (error) {
console.error('Error in cancelling leave candidates request:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**candidateBondMore**(more) - request to increase a candidate's self bond by a specified amount"
=== "Parameters"
- `more` - The amount of WEI by which to increase the candidate's self bond
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup candidate account from private key
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const candidate = keyring.addFromUri(PRIVATE_KEY);
// Amount to increase bond by (e.g., 1 DEV = 1_000_000_000_000_000_000)
const moreBond = '1000000000000000000';
console.log('Candidate address:', candidate.address);
console.log('Increasing bond by:', moreBond, 'Wei (1 DEV)');
// Query current bond before increasing
const candidateInfo = await api.query.parachainStaking.candidateInfo(
candidate.address
);
if (candidateInfo.isSome) {
console.log('Current bond:', candidateInfo.unwrap().bond.toString());
}
// Create the increase bond transaction
const tx = api.tx.parachainStaking.candidateBondMore(moreBond);
// Sign and send the transaction
await tx.signAndSend(candidate, ({ status, events }) => {
if (status.isInBlock) {
console.log(`Transaction included in block hash: ${status.asInBlock}`);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful bond increase
if (
section === 'parachainStaking' &&
method === 'CandidateBondedMore'
) {
const [candidateAddress, amount, newTotal] = data;
console.log('\nSuccessfully increased candidate bond!');
console.log('Candidate:', candidateAddress.toString());
console.log('Amount increased:', amount.toString());
console.log('New total bond:', newTotal.toString());
}
});
// Query updated bond after transaction
api.query.parachainStaking
.candidateInfo(candidate.address)
.then((newInfo) => {
if (newInfo.isSome) {
console.log('\nUpdated bond:', newInfo.unwrap().bond.toString());
}
process.exit(0);
});
}
});
} catch (error) {
console.error('Error in increasing candidate bond:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**delegateWithAutoCompound**(candidate, amount, autoCompound, candidateDelegationCount, candidateAutoCompoundingDelegationCount, delegationCount) - delegates a collator candidate and sets the percentage of rewards to auto-compound given an integer (no decimals) for the `amount` between 0-100. If the caller is not a delegator, this function adds them to the set of delegators. If the caller is already a delegator, then it adjusts their delegation amount"
=== "Parameters"
- `candidate` - The collator's address you want to delegate to
- `amount` - The amount to delegate (in Wei, e.g. 1000000000000000000 for 1 DEV)
- `autoCompound` - The percentage of rewards to automatically compound (0-100)
- `candidateDelegationCount` - The current number of delegations to the collator
- `candidateAutoCompoundingDelegationCount` - The current number of auto-compounding delegations for the collator
- `delegationCount` - The total number of delegations you have across all collators
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup delegator account from private key
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const delegator = keyring.addFromUri(PRIVATE_KEY);
// The candidate's address to delegate to
const candidateAddress = 'INSERT_COLLATOR_ADDRESS';
// Amount to delegate (e.g., 1 DEV = 1_000_000_000_000_000_000)
const amount = '1000000000000000000';
// Auto-compound percentage (0-100)
const autoCompound = 50; // 50% of rewards will be auto-compounded
// Get current delegation counts
const candidateInfo =
await api.query.parachainStaking.candidateInfo(candidateAddress);
const delegatorState = await api.query.parachainStaking.delegatorState(
delegator.address
);
const autoCompoundDelegations =
await api.query.parachainStaking.autoCompoundingDelegations(
candidateAddress
);
// Get delegation counts
let candidateDelegationCount = 0;
let candidateAutoCompoundingDelegationCount = 0;
let delegationCount = 0;
if (candidateInfo.isSome) {
candidateDelegationCount = candidateInfo.unwrap().delegationCount;
}
candidateAutoCompoundingDelegationCount = autoCompoundDelegations.length;
if (delegatorState.isSome) {
delegationCount = delegatorState.unwrap().delegations.length;
}
console.log('Delegation Details:');
console.log('Delegator address:', delegator.address);
console.log('Candidate address:', candidateAddress);
console.log('Delegation amount:', amount, 'Wei (1 DEV)');
console.log('Auto-compound percentage:', autoCompound, '%');
console.log('\nCurrent Stats:');
console.log(
'Candidate delegation count:',
candidateDelegationCount.toString()
);
console.log(
'Candidate auto-compounding delegation count:',
candidateAutoCompoundingDelegationCount.toString()
);
console.log('Delegator total delegations:', delegationCount.toString());
// Create the delegate with auto-compound transaction
const tx = api.tx.parachainStaking.delegateWithAutoCompound(
candidateAddress,
amount,
autoCompound,
candidateDelegationCount,
candidateAutoCompoundingDelegationCount,
delegationCount
);
// Sign and send the transaction
await tx.signAndSend(delegator, ({ status, events }) => {
if (status.isInBlock) {
console.log(
`\nTransaction included in block hash: ${status.asInBlock}`
);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful delegation
if (section === 'parachainStaking' && method === 'Delegation') {
const [delegator, amount, candidate, autoCompound] = data;
console.log('\nSuccessfully delegated with auto-compound!');
console.log('Delegator:', delegator.toString());
console.log('Candidate:', candidate.toString());
console.log('Amount:', amount.toString());
console.log(
'Auto-compound percentage:',
autoCompound.toString(),
'%'
);
}
});
process.exit(0);
}
});
} catch (error) {
console.error('Error in delegation with auto-compound:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**delegatorBondMore**(candidate, more) - request to increase a delegator's amount delegated for a specific candidate"
=== "Parameters"
- `candidate` - the address of the respective collator
- `more` - The amount you want to increase your delegation by (in Wei, e.g. 1000000000000000000 for 1 DEV)
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup delegator account from private key
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const delegator = keyring.addFromUri(PRIVATE_KEY);
// The candidate's address for which to increase delegation
const candidateAddress = 'INSERT_COLLATOR_ADDRESS';
// Amount to increase delegation by (e.g., 1 DEV = 1_000_000_000_000_000_000)
const moreBond = '1000000000000000000';
// Query current delegation before increasing
const delegatorState = await api.query.parachainStaking.delegatorState(
delegator.address
);
console.log('Current Delegation Info:');
console.log('Delegator address:', delegator.address);
console.log('Candidate address:', candidateAddress);
if (delegatorState.isSome) {
const state = delegatorState.unwrap();
const currentDelegation = state.delegations.find(
(d) =>
d.owner.toString().toLowerCase() === candidateAddress.toLowerCase()
);
if (currentDelegation) {
console.log(
'Current delegation amount:',
currentDelegation.amount.toString()
);
}
}
console.log('Amount to increase by:', moreBond, 'Wei (1 DEV)');
// Create the increase delegation transaction
const tx = api.tx.parachainStaking.delegatorBondMore(
candidateAddress,
moreBond
);
// Sign and send the transaction
await tx.signAndSend(delegator, ({ status, events }) => {
if (status.isInBlock) {
console.log(
`\nTransaction included in block hash: ${status.asInBlock}`
);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful bond increase
if (
section === 'parachainStaking' &&
method === 'DelegationIncreased'
) {
const [delegator, candidate, amount, inTopDelegations] = data;
console.log('\nSuccessfully increased delegation!');
console.log('Delegator:', delegator.toString());
console.log('Candidate:', candidate.toString());
console.log('Amount increased by:', amount.toString());
console.log('In top delegations:', inTopDelegations.toString());
}
});
// Query updated delegation after transaction
api.query.parachainStaking
.delegatorState(delegator.address)
.then((newState) => {
if (newState.isSome) {
const state = newState.unwrap();
const updatedDelegation = state.delegations.find(
(d) =>
d.owner.toString().toLowerCase() ===
candidateAddress.toLowerCase()
);
if (updatedDelegation) {
console.log(
'\nNew delegation amount:',
updatedDelegation.amount.toString()
);
}
}
process.exit(0);
});
}
});
} catch (error) {
console.error('Error in increasing delegation:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**executeCandidateBondLess**(candidate) - executes any scheduled due requests to decrease a candidate's self bond amount"
=== "Parameters"
- `candidate` - the address of the respective collator
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup account from private key (this can be any account, doesn't need to be the candidate)
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const executor = keyring.addFromUri(PRIVATE_KEY);
// The candidate's address whose bond decrease should be executed
const candidateAddress = 'INSERT_COLLATOR_ADDRESS';
// Query current candidate info before execution
const candidateInfo =
await api.query.parachainStaking.candidateInfo(candidateAddress);
console.log('Execution Details:');
console.log('Executor address:', executor.address);
console.log('Candidate address:', candidateAddress);
if (candidateInfo.isSome) {
const info = candidateInfo.unwrap();
console.log('\nCandidate current bond:', info.bond.toString());
console.log('Candidate status:', info.status.toString());
}
// Create the execute bond decrease transaction
const tx =
api.tx.parachainStaking.executeCandidateBondLess(candidateAddress);
// Sign and send the transaction
await tx.signAndSend(executor, ({ status, events }) => {
if (status.isInBlock) {
console.log(
`\nTransaction included in block hash: ${status.asInBlock}`
);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful execution
if (
section === 'parachainStaking' &&
method === 'CandidateBondedLess'
) {
const [candidate, amount, newBond] = data;
console.log('\nSuccessfully executed candidate bond decrease!');
console.log('Candidate:', candidate.toString());
console.log('Amount decreased:', amount.toString());
console.log('New bond amount:', newBond.toString());
}
});
// Query updated candidate info after execution
api.query.parachainStaking
.candidateInfo(candidateAddress)
.then((newInfo) => {
if (newInfo.isSome) {
const info = newInfo.unwrap();
console.log('\nUpdated candidate bond:', info.bond.toString());
}
process.exit(0);
});
}
});
} catch (error) {
console.error('Error in executing candidate bond decrease:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**executeDelegationRequest**(delegator, candidate) - executes any scheduled due delegation requests for a specific delegator provided the address of the candidate"
=== "Parameters"
- `delegator` - The address of the delegator who made the delegation request
- `candidate` - The collator's address associated with the delegation request
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup executor account from private key (this can be any account)
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const executor = keyring.addFromUri(PRIVATE_KEY);
// The delegator's address whose request will be executed
const delegatorAddress = 'INSERT_DELEGATOR_ADDRESS';
// The candidate's address for the delegation request
const candidateAddress = 'INSERT_COLLATOR_ADDRESS';
// Query current delegation info before execution
const delegatorState =
await api.query.parachainStaking.delegatorState(delegatorAddress);
console.log('Execution Details:');
console.log('Executor address:', executor.address);
console.log('Delegator address:', delegatorAddress);
console.log('Candidate address:', candidateAddress);
if (delegatorState.isSome) {
const state = delegatorState.unwrap();
const currentDelegation = state.delegations.find(
(d) =>
d.owner.toString().toLowerCase() === candidateAddress.toLowerCase()
);
if (currentDelegation) {
console.log(
'\nCurrent delegation amount:',
currentDelegation.amount.toString()
);
}
}
// Create the execute delegation request transaction
const tx = api.tx.parachainStaking.executeDelegationRequest(
delegatorAddress,
candidateAddress
);
// Sign and send the transaction
await tx.signAndSend(executor, ({ status, events }) => {
if (status.isInBlock) {
console.log(
`\nTransaction included in block hash: ${status.asInBlock}`
);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful delegation decrease/revoke
if (
section === 'parachainStaking' &&
method === 'DelegationDecreased'
) {
const [delegator, candidate, amount, inTopDelegations] = data;
console.log('\nSuccessfully executed delegation decrease!');
console.log('Delegator:', delegator.toString());
console.log('Candidate:', candidate.toString());
console.log('Amount decreased:', amount.toString());
console.log('In top delegations:', inTopDelegations.toString());
}
if (
section === 'parachainStaking' &&
method === 'DelegationRevoked'
) {
const [delegator, candidate, amount] = data;
console.log('\nSuccessfully executed delegation revocation!');
console.log('Delegator:', delegator.toString());
console.log('Candidate:', candidate.toString());
console.log('Amount revoked:', amount.toString());
}
});
// Query updated delegation info after execution
api.query.parachainStaking
.delegatorState(delegatorAddress)
.then((newState) => {
if (newState.isSome) {
const state = newState.unwrap();
const updatedDelegation = state.delegations.find(
(d) =>
d.owner.toString().toLowerCase() ===
candidateAddress.toLowerCase()
);
if (updatedDelegation) {
console.log(
'\nNew delegation amount:',
updatedDelegation.amount.toString()
);
} else {
console.log('\nDelegation has been fully revoked');
}
}
process.exit(0);
});
}
});
} catch (error) {
console.error('Error in executing delegation request:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**executeLeaveCandidates**(candidate, candidateDelegationCount) - executes any scheduled due requests to leave the set of collator candidates"
=== "Parameters"
- `candidate` - The address of the collator who requested to leave the candidate pool
- `candidateDelegationCount` - The current number of delegations for the leaving candidate
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup executor account from private key (this can be any account)
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const executor = keyring.addFromUri(PRIVATE_KEY);
// The candidate's address who is scheduled to leave
const candidateAddress = 'INSERT_COLLATOR_ADDRESS';
// Get candidate information and delegation count
const candidateInfo =
await api.query.parachainStaking.candidateInfo(candidateAddress);
let candidateDelegationCount = 0;
console.log('Execution Details:');
console.log('Executor address:', executor.address);
console.log('Candidate address:', candidateAddress);
if (candidateInfo.isSome) {
const info = candidateInfo.unwrap();
candidateDelegationCount = info.delegationCount;
console.log('\nCandidate Information:');
console.log('Current bond:', info.bond.toString());
console.log('Delegation count:', candidateDelegationCount.toString());
console.log('Status:', info.status.toString());
} else {
console.log('\nWarning: Candidate info not found');
}
// Create the execute leave candidates transaction
const tx = api.tx.parachainStaking.executeLeaveCandidates(
candidateAddress,
candidateDelegationCount
);
// Sign and send the transaction
await tx.signAndSend(executor, ({ status, events }) => {
if (status.isInBlock) {
console.log(
`\nTransaction included in block hash: ${status.asInBlock}`
);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful execution of leave request
if (section === 'parachainStaking' && method === 'CandidateLeft') {
const [candidate, amount, remainingCount] = data;
console.log('\nSuccessfully executed leave candidates request!');
console.log('Candidate:', candidate.toString());
console.log('Amount unlocked:', amount.toString());
console.log('Remaining candidates:', remainingCount.toString());
}
});
// Query final candidate state
api.query.parachainStaking
.candidateInfo(candidateAddress)
.then((finalState) => {
if (finalState.isNone) {
console.log(
'\nCandidate has been successfully removed from the candidate pool'
);
} else {
console.log('\nWarning: Candidate still exists in the pool');
console.log('Current state:', finalState.unwrap().toString());
}
process.exit(0);
});
}
});
} catch (error) {
console.error('Error in executing leave candidates request:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**goOffline**() - allows a collator candidate to temporarily leave the pool of candidates without unbonding"
=== "Parameters"
None
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup collator account from private key
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const collator = keyring.addFromUri(PRIVATE_KEY);
// Query current collator info before going offline
const candidateInfo = await api.query.parachainStaking.candidateInfo(
collator.address
);
console.log('Collator Details:');
console.log('Collator address:', collator.address);
if (candidateInfo.isSome) {
const info = candidateInfo.unwrap();
console.log('\nCurrent Status:');
console.log('Bond:', info.bond.toString());
console.log('Delegation Count:', info.delegationCount.toString());
console.log('Status:', info.status.toString());
} else {
console.log('\nWarning: Not found in candidate pool');
process.exit(1);
}
// Create the go offline transaction
const tx = api.tx.parachainStaking.goOffline();
// Sign and send the transaction
await tx.signAndSend(collator, ({ status, events }) => {
if (status.isInBlock) {
console.log(
`\nTransaction included in block hash: ${status.asInBlock}`
);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful offline status change
if (
section === 'parachainStaking' &&
method === 'CandidateWentOffline'
) {
const [collatorAccount] = data;
console.log('\nSuccessfully went offline!');
console.log('Collator:', collatorAccount.toString());
}
});
// Query final collator state
api.query.parachainStaking
.candidateInfo(collator.address)
.then((finalState) => {
if (finalState.isSome) {
const info = finalState.unwrap();
console.log('\nUpdated Status:');
console.log('Bond:', info.bond.toString());
console.log('Delegation Count:', info.delegationCount.toString());
console.log('Status:', info.status.toString());
}
process.exit(0);
});
}
});
} catch (error) {
console.error('Error in going offline:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**goOnline**() - allows a collator candidate to rejoin the pool of candidates after previously calling `goOffline()`"
=== "Parameters"
None
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup collator account from private key
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const collator = keyring.addFromUri(PRIVATE_KEY);
// Query current collator info before going online
const candidateInfo = await api.query.parachainStaking.candidateInfo(
collator.address
);
console.log('Collator Details:');
console.log('Collator address:', collator.address);
if (candidateInfo.isSome) {
const info = candidateInfo.unwrap();
console.log('\nCurrent Status:');
console.log('Bond:', info.bond.toString());
console.log('Delegation Count:', info.delegationCount.toString());
console.log('Status:', info.status.toString());
} else {
console.log('\nWarning: Not found in candidate pool');
process.exit(1);
}
// Create the go online transaction
const tx = api.tx.parachainStaking.goOnline();
// Sign and send the transaction
await tx.signAndSend(collator, ({ status, events }) => {
if (status.isInBlock) {
console.log(
`\nTransaction included in block hash: ${status.asInBlock}`
);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful online status change
if (
section === 'parachainStaking' &&
method === 'CandidateBackOnline'
) {
const [collatorAccount] = data;
console.log('\nSuccessfully went back online!');
console.log('Collator:', collatorAccount.toString());
}
});
// Query final collator state
api.query.parachainStaking
.candidateInfo(collator.address)
.then((finalState) => {
if (finalState.isSome) {
const info = finalState.unwrap();
console.log('\nUpdated Status:');
console.log('Bond:', info.bond.toString());
console.log('Delegation Count:', info.delegationCount.toString());
console.log('Status:', info.status.toString());
}
process.exit(0);
});
}
});
} catch (error) {
console.error('Error in going online:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**joinCandidates**(bond, candidateCount) - request to join the set of collator candidates with a specified bond amount and provided the current candidate count"
=== "Parameters"
- `bond` - The amount to stake as collator bond (in Wei, e.g. 500000000000000000000 for 500 DEV)
- `candidateCount` - The total number of candidates currently in the candidate pool
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup account from private key
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const account = keyring.addFromUri(PRIVATE_KEY);
// Set bond amount to 500 DEV (multiply by 10^18 for proper decimals)
const bondAmount = '500000000000000000000';
// Get current candidate count
const candidates = await api.query.parachainStaking.candidatePool();
const candidateCount = candidates.length;
// Check account balance
const balance = await api.query.system.account(account.address);
console.log('Join Candidates Details:');
console.log('Account address:', account.address);
console.log('Current free balance:', balance.data.free.toString());
console.log('Bond amount:', bondAmount, '(501 DEV)');
console.log('Current candidate count:', candidateCount);
// Create the join candidates transaction
const tx = api.tx.parachainStaking.joinCandidates(
bondAmount,
candidateCount
);
// Sign and send the transaction
await tx.signAndSend(account, ({ status, events }) => {
if (status.isInBlock) {
console.log(
`\nTransaction included in block hash: ${status.asInBlock}`
);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful joining
if (
section === 'parachainStaking' &&
method === 'JoinedCollatorCandidates'
) {
const [account, amountLocked, newTotalAmountLocked] = data;
console.log('\nSuccessfully joined collator candidates!');
console.log('Account:', account.toString());
console.log('Amount locked:', amountLocked.toString());
console.log(
'New total amount locked:',
newTotalAmountLocked.toString()
);
}
});
// Query final candidate state
api.query.parachainStaking
.candidateInfo(account.address)
.then((finalState) => {
if (finalState.isSome) {
const info = finalState.unwrap();
console.log('\nNew Candidate Status:');
console.log('Bond:', info.bond.toString());
console.log('Delegation Count:', info.delegationCount.toString());
console.log('Status:', info.status.toString());
}
// Get updated candidate count
api.query.parachainStaking.candidatePool().then((newCandidates) => {
console.log('New candidate count:', newCandidates.length);
process.exit(0);
});
});
}
});
} catch (error) {
console.error('Error in joining candidates:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**notifyInactiveCollator**(collator) - marks a collator as inactive if they have not been producing blocks for the maximum number of offline rounds, as returned by the [`maxOfflineRounds` pallet constant](#constants)"
=== "Parameters"
- `collator` - the address of the collator to be notified
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup notifier account from private key (this can be any account)
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const notifier = keyring.addFromUri(PRIVATE_KEY);
// The potentially inactive collator's address
const inactiveCollator = 'INSERT_COLLATOR_ADDRESS';
// Get max offline rounds from constants
const maxOfflineRounds = await api.consts.parachainStaking.maxOfflineRounds;
// Get current round info
const round = await api.query.parachainStaking.round();
// Get collator info
const collatorInfo =
await api.query.parachainStaking.candidateInfo(inactiveCollator);
console.log('Notify Inactive Collator Details:');
console.log('Notifier address:', notifier.address);
console.log('Inactive collator address:', inactiveCollator);
console.log('Maximum allowed offline rounds:', maxOfflineRounds.toString());
console.log('Current round:', round.current.toString());
if (collatorInfo.isSome) {
const info = collatorInfo.unwrap();
console.log('\nCollator Current Status:');
console.log('Bond:', info.bond.toString());
console.log('Delegation Count:', info.delegationCount.toString());
console.log('Status:', info.status.toString());
}
// Create the notify inactive collator transaction
const tx = api.tx.parachainStaking.notifyInactiveCollator(inactiveCollator);
// Sign and send the transaction
await tx.signAndSend(notifier, ({ status, events }) => {
if (status.isInBlock) {
console.log(
`\nTransaction included in block hash: ${status.asInBlock}`
);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful notification
if (
section === 'parachainStaking' &&
method === 'CollatorWentOffline'
) {
const [collatorAccount] = data;
console.log('\nSuccessfully notified inactive collator!');
console.log('Collator:', collatorAccount.toString());
}
});
// Query final collator state
api.query.parachainStaking
.candidateInfo(inactiveCollator)
.then((finalState) => {
if (finalState.isSome) {
const info = finalState.unwrap();
console.log('\nUpdated Collator Status:');
console.log('Bond:', info.bond.toString());
console.log('Delegation Count:', info.delegationCount.toString());
console.log('Status:', info.status.toString());
}
process.exit(0);
});
}
});
} catch (error) {
console.error('Error in notifying inactive collator:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**scheduleCandidateBondLess**(less) - schedules a request to decrease a candidate's self bond by a specified amount. There is an [exit delay](#exit-delays) that must be waited before you can execute the request via the `executeCandidateBondLess` extrinsic"
=== "Parameters"
- `less` - The amount you want to decrease your delegation by (in Wei, e.g. 1000000000000000000 for 1 DEV)
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup candidate account from private key
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const candidate = keyring.addFromUri(PRIVATE_KEY);
// Amount to decrease bond by (e.g., 1 DEV = 1_000_000_000_000_000_000)
const decreaseAmount = '1000000000000000000'; // 1 DEV
// Get current candidate info
const candidateInfo = await api.query.parachainStaking.candidateInfo(
candidate.address
);
console.log('Schedule Bond Decrease Details:');
console.log('Candidate address:', candidate.address);
console.log('Bond decrease amount:', decreaseAmount, 'Wei (1 DEV)');
if (candidateInfo.isSome) {
const info = candidateInfo.unwrap();
console.log('\nCurrent Candidate Status:');
console.log('Current bond:', info.bond.toString());
console.log('Delegation Count:', info.delegationCount.toString());
console.log('Status:', info.status.toString());
} else {
console.log('\nWarning: Account is not a candidate');
process.exit(1);
}
// Create the schedule bond decrease transaction
const tx =
api.tx.parachainStaking.scheduleCandidateBondLess(decreaseAmount);
// Get current round
const round = await api.query.parachainStaking.round();
const currentRound = round.current.toNumber();
// Sign and send the transaction
await tx.signAndSend(candidate, ({ status, events }) => {
if (status.isInBlock) {
console.log(
`\nTransaction included in block hash: ${status.asInBlock}`
);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful scheduling
if (
section === 'parachainStaking' &&
method === 'CandidateBondLessRequested'
) {
const [candidate, amountToDecrease, executeRound] = data;
console.log('\nSuccessfully scheduled bond decrease!');
console.log('Candidate:', candidate.toString());
console.log('Amount to decrease:', amountToDecrease.toString());
console.log('Execute round:', executeRound.toString());
console.log(
`\nNote: You must wait until round ${executeRound.toString()} to execute the decrease request`
);
}
});
// Query final candidate state
api.query.parachainStaking
.candidateInfo(candidate.address)
.then((finalState) => {
if (finalState.isSome) {
const info = finalState.unwrap();
console.log('\nUpdated Candidate Status:');
console.log('Bond:', info.bond.toString());
console.log('Delegation Count:', info.delegationCount.toString());
console.log('Status:', info.status.toString());
}
process.exit(0);
});
}
});
} catch (error) {
console.error('Error in scheduling bond decrease:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**scheduleDelegatorBondLess**(candidate, less) - schedules a request for a delegator to bond less with respect to a specific candidate. There is an [exit delay](#exit-delays) that must be waited before you can execute the request via the `executeDelegationRequest` extrinsic"
=== "Parameters"
- `candidate` - The collator's address for which you want to decrease your delegation
- `less` - The amount you want to decrease your delegation by (in Wei, e.g. 1000000000000000000 for 1 DEV)
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup delegator account from private key
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const delegator = keyring.addFromUri(PRIVATE_KEY);
// The candidate's address to decrease delegation for
const candidateAddress = 'INSERT_COLLATOR_ADDRESS';
// Amount to decrease delegation by (e.g., 1 DEV = 1_000_000_000_000_000_000)
const decreaseAmount = '1000000000000000000'; // 1 DEV
// Get current delegation info
const delegatorState = await api.query.parachainStaking.delegatorState(
delegator.address
);
console.log('Schedule Delegation Decrease Details:');
console.log('Delegator address:', delegator.address);
console.log('Candidate address:', candidateAddress);
console.log('Amount to decrease:', decreaseAmount, 'Wei (1 DEV)');
if (delegatorState.isSome) {
const state = delegatorState.unwrap();
const currentDelegation = state.delegations.find(
(d) =>
d.owner.toString().toLowerCase() === candidateAddress.toLowerCase()
);
if (currentDelegation) {
console.log(
'\nCurrent Delegation Amount:',
currentDelegation.amount.toString()
);
} else {
console.log(
'\nWarning: No existing delegation found for this candidate'
);
process.exit(1);
}
} else {
console.log('\nWarning: Account is not a delegator');
process.exit(1);
}
// Get current round
const round = await api.query.parachainStaking.round();
console.log('Current round:', round.current.toString());
// Create the schedule decrease transaction
const tx = api.tx.parachainStaking.scheduleDelegatorBondLess(
candidateAddress,
decreaseAmount
);
// Sign and send the transaction
await tx.signAndSend(delegator, ({ status, events }) => {
if (status.isInBlock) {
console.log(
`\nTransaction included in block hash: ${status.asInBlock}`
);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful scheduling
if (
section === 'parachainStaking' &&
method === 'DelegationDecreaseScheduled'
) {
const [delegator, candidate, amountToDecrease, executeRound] = data;
console.log('\nSuccessfully scheduled delegation decrease!');
console.log('Delegator:', delegator.toString());
console.log('Candidate:', candidate.toString());
console.log('Amount to decrease:', amountToDecrease.toString());
console.log('Execute round:', executeRound.toString());
console.log(
`\nNote: You must wait until round ${executeRound.toString()} to execute the decrease request`
);
}
});
// Query final delegation state
api.query.parachainStaking
.delegatorState(delegator.address)
.then((finalState) => {
if (finalState.isSome) {
const state = finalState.unwrap();
const updatedDelegation = state.delegations.find(
(d) =>
d.owner.toString().toLowerCase() ===
candidateAddress.toLowerCase()
);
if (updatedDelegation) {
console.log('\nCurrent Delegation Status:');
console.log('Amount:', updatedDelegation.amount.toString());
console.log(
'Note: Amount will decrease after execution in the scheduled round'
);
}
}
process.exit(0);
});
}
});
} catch (error) {
console.error('Error in scheduling delegation decrease:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**scheduleLeaveCandidates**(candidateCount) - schedules a request for a candidate to remove themselves from the candidate pool. There is an [exit delay](#exit-delays) that must be waited before you can execute the request via the `executeLeaveCandidates` extrinsic"
=== "Parameters"
- `candidateCount` - The total number of candidates currently in the candidate pool
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup collator account from private key
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const collator = keyring.addFromUri(PRIVATE_KEY);
// Get current candidate pool information
const candidates = await api.query.parachainStaking.candidatePool();
const candidateCount = candidates.length;
// Get current candidate info
const candidateInfo = await api.query.parachainStaking.candidateInfo(
collator.address
);
console.log('Schedule Leave Details:');
console.log('Collator address:', collator.address);
console.log('Current candidate count:', candidateCount);
if (candidateInfo.isSome) {
const info = candidateInfo.unwrap();
console.log('\nCurrent Candidate Status:');
console.log('Bond:', info.bond.toString());
console.log('Delegation Count:', info.delegationCount.toString());
console.log('Status:', info.status.toString());
} else {
console.log('\nWarning: Account is not a candidate');
process.exit(1);
}
// Create the schedule leave transaction
const tx = api.tx.parachainStaking.scheduleLeaveCandidates(candidateCount);
// Get the current round
const round = await api.query.parachainStaking.round();
const currentRound = round.current.toNumber();
// Sign and send the transaction
await tx.signAndSend(collator, ({ status, events }) => {
if (status.isInBlock) {
console.log(
`\nTransaction included in block hash: ${status.asInBlock}`
);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful scheduling
if (
section === 'parachainStaking' &&
method === 'CandidateScheduledExit'
) {
const [round, candidate, scheduledExit] = data;
console.log('\nSuccessfully scheduled leave candidates!');
console.log('Candidate:', candidate.toString());
console.log('Current round:', round.toString());
console.log('Scheduled exit round:', scheduledExit.toString());
console.log(
`\nNote: You must wait until round ${scheduledExit.toString()} to execute the leave request`
);
}
});
// Query final candidate state
api.query.parachainStaking
.candidateInfo(collator.address)
.then((finalState) => {
if (finalState.isSome) {
const info = finalState.unwrap();
console.log('\nUpdated Candidate Status:');
console.log('Bond:', info.bond.toString());
console.log('Delegation Count:', info.delegationCount.toString());
console.log(
'Status:',
info.status.toString(),
'(Leaving status shows the exit round)'
);
}
process.exit(0);
});
}
});
} catch (error) {
console.error('Error in scheduling leave candidates:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**scheduleRevokeDelegation**(collator) - schedules a request to revoke a delegation given the address of a candidate. There is an [exit delay](#exit-delays) that must be waited before you can execute the request via the `executeDelegationRequest` extrinsic"
=== "Parameters"
- `collator` - The collator's address from which you want to revoke your delegation
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup delegator account from private key
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const delegator = keyring.addFromUri(PRIVATE_KEY);
// The collator's address to revoke delegation from
const collatorAddress = 'INSERT_COLLATOR_ADDRESS';
// Get current delegation info
const delegatorState = await api.query.parachainStaking.delegatorState(
delegator.address
);
console.log('Schedule Revoke Delegation Details:');
console.log('Delegator address:', delegator.address);
console.log('Collator address:', collatorAddress);
if (delegatorState.isSome) {
const state = delegatorState.unwrap();
const currentDelegation = state.delegations.find(
(d) =>
d.owner.toString().toLowerCase() === collatorAddress.toLowerCase()
);
if (currentDelegation) {
console.log(
'\nCurrent Delegation Amount:',
currentDelegation.amount.toString()
);
} else {
console.log(
'\nWarning: No existing delegation found for this collator'
);
process.exit(1);
}
} else {
console.log('\nWarning: Account is not a delegator');
process.exit(1);
}
// Get current round
const round = await api.query.parachainStaking.round();
console.log('Current round:', round.current.toString());
// Create the schedule revoke transaction
const tx =
api.tx.parachainStaking.scheduleRevokeDelegation(collatorAddress);
// Sign and send the transaction
await tx.signAndSend(delegator, ({ status, events }) => {
if (status.isInBlock) {
console.log(
`\nTransaction included in block hash: ${status.asInBlock}`
);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful scheduling
if (
section === 'parachainStaking' &&
method === 'DelegationRevocationScheduled'
) {
const [round, delegator, candidate, executeRound] = data;
console.log('\nSuccessfully scheduled delegation revocation!');
console.log('Round:', round.toString());
console.log('Delegator:', delegator.toString());
console.log('Collator:', candidate.toString());
console.log('Execute round:', executeRound.toString());
console.log(
`\nNote: You must wait until round ${executeRound.toString()} to execute the revocation request`
);
}
});
// Query final delegation state
api.query.parachainStaking
.delegatorState(delegator.address)
.then((finalState) => {
if (finalState.isSome) {
const state = finalState.unwrap();
const updatedDelegation = state.delegations.find(
(d) =>
d.owner.toString().toLowerCase() ===
collatorAddress.toLowerCase()
);
if (updatedDelegation) {
console.log('\nCurrent Delegation Status:');
console.log('Amount:', updatedDelegation.amount.toString());
console.log(
'Note: Delegation will be fully revoked after execution in the scheduled round'
);
}
}
process.exit(0);
});
}
});
} catch (error) {
console.error('Error in scheduling delegation revocation:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**setAutoCompound**(candidate, value, candidateAutoCompoundingDelegationCountHint, delegationCountHint) - sets the percentage of rewards to be auto-compounded for an existing delegation given an integer (no decimals) for the `value` between 0-100"
=== "Parameters"
- `candidate` - The collator's address you're delegating to
- `value` - Auto-compound percentage (0-100)
- `candidateAutoCompoundingDelegationCountHint` - Number of auto-compounding delegations for this collator
- `delegationCountHint` - Total number of delegations you have across all collators
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
// Initialize the keyring with ethereum type
const keyring = new Keyring({ type: 'ethereum' });
try {
// Setup delegator account from private key
const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
const delegator = keyring.addFromUri(PRIVATE_KEY);
// The candidate's address for the delegation
const candidateAddress = 'INSERT_COLLATOR_ADDRESS';
// Auto-compound percentage (0-100)
const autoCompoundValue = 50; // 50% of rewards will be auto-compounded
// Get auto-compounding delegations count
const autoCompoundDelegations =
await api.query.parachainStaking.autoCompoundingDelegations(
candidateAddress
);
const candidateAutoCompoundingDelegationCount =
autoCompoundDelegations.length;
// Get delegator state for delegation count
const delegatorState = await api.query.parachainStaking.delegatorState(
delegator.address
);
let delegationCount = 0;
console.log('Set Auto-Compound Details:');
console.log('Delegator address:', delegator.address);
console.log('Candidate address:', candidateAddress);
console.log('Auto-compound percentage:', autoCompoundValue, '%');
if (delegatorState.isSome) {
const state = delegatorState.unwrap();
delegationCount = state.delegations.length;
const currentDelegation = state.delegations.find(
(d) =>
d.owner.toString().toLowerCase() === candidateAddress.toLowerCase()
);
if (currentDelegation) {
console.log(
'\nCurrent Delegation Amount:',
currentDelegation.amount.toString()
);
} else {
console.log(
'\nWarning: No existing delegation found for this candidate'
);
process.exit(1);
}
} else {
console.log('\nWarning: Account is not a delegator');
process.exit(1);
}
console.log('\nDelegation Counts:');
console.log(
'Auto-compounding delegations:',
candidateAutoCompoundingDelegationCount
);
console.log('Total delegations:', delegationCount);
// Create the set auto-compound transaction
const tx = api.tx.parachainStaking.setAutoCompound(
candidateAddress,
autoCompoundValue,
candidateAutoCompoundingDelegationCount,
delegationCount
);
// Sign and send the transaction
await tx.signAndSend(delegator, ({ status, events }) => {
if (status.isInBlock) {
console.log(
`\nTransaction included in block hash: ${status.asInBlock}`
);
// Process events
events.forEach(({ event }) => {
const { section, method, data } = event;
console.log(`\t${section}.${method}:`, data.toString());
// Handle any failures
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data;
let errorInfo;
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(
dispatchError.asModule
);
errorInfo = `${decoded.section}.${decoded.name}: ${decoded.docs}`;
} else {
errorInfo = dispatchError.toString();
}
console.error('Failure reason:', errorInfo);
}
// Log successful auto-compound setting
if (section === 'parachainStaking' && method === 'AutoCompoundSet') {
const [candidate, delegator, value] = data;
console.log('\nSuccessfully set auto-compound percentage!');
console.log('Candidate:', candidate.toString());
console.log('Delegator:', delegator.toString());
console.log('Auto-compound value:', value.toString(), '%');
}
});
// Query updated auto-compound settings
api.query.parachainStaking
.autoCompoundingDelegations(candidateAddress)
.then((newAutoCompound) => {
const delegatorSetting = newAutoCompound.find(
(d) =>
d.delegator.toString().toLowerCase() ===
delegator.address.toLowerCase()
);
if (delegatorSetting) {
console.log('\nUpdated Auto-Compound Setting:');
console.log('Value:', delegatorSetting.value.toString(), '%');
}
process.exit(0);
});
}
});
} catch (error) {
console.error('Error in setting auto-compound:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
### Storage Methods {: #storage-methods }
The parachain staking pallet includes the following read-only storage methods to obtain chain state data:
??? function "**atStake**(u32, AccountId20) - provides a snapshot of a collator's delegation stake and the percentage of rewards set to auto-compound given a round number and, optionally, the collator's address"
=== "Parameters"
- `u32` - round number
- `AccountId20` - collator address to query. If omitted, information about all collators will be returned
=== "Returns"
Information about a collator's delegations including delegator addresses, amounts, and auto-compound percentages
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get current round information
const round = await api.query.parachainStaking.round();
const currentRound = round.current.toNumber();
// Example collator address
const collatorAddress = 'INSERT_COLLATOR_ADDRESS';
console.log('Query Parameters:');
console.log('Current round:', currentRound);
console.log('Collator address:', collatorAddress);
// Query current round
console.log('\nQuerying current round stake...');
const currentStake = await api.query.parachainStaking.atStake(
currentRound,
collatorAddress
);
if (currentStake) {
console.log('\nCurrent Round Stake Details:');
const stakeInfo = currentStake.toHuman();
console.log(JSON.stringify(stakeInfo, null, 2));
// Get raw values for calculations if needed
const rawStake = currentStake.toJSON();
console.log('\nRaw Stake Values:');
console.log('Total stake:', rawStake.total);
console.log('Own stake:', rawStake.bond);
}
// Query previous round
const previousRound = currentRound - 1;
console.log('\nQuerying previous round stake...');
const previousStake = await api.query.parachainStaking.atStake(
previousRound,
collatorAddress
);
if (previousStake) {
console.log('\nPrevious Round Stake Details:');
const previousStakeInfo = previousStake.toHuman();
console.log(JSON.stringify(previousStakeInfo, null, 2));
}
// Get scheduled delegation requests
const delegationRequests =
await api.query.parachainStaking.delegationScheduledRequests(
collatorAddress
);
console.log('\nScheduled Delegation Changes:');
if (delegationRequests.length > 0) {
console.log(JSON.stringify(delegationRequests.toHuman(), null, 2));
} else {
console.log('No scheduled delegation changes');
}
// Get auto-compound settings
const autoCompound =
await api.query.parachainStaking.autoCompoundingDelegations(
collatorAddress
);
console.log('\nAuto-Compound Settings:');
if (autoCompound.length > 0) {
console.log(JSON.stringify(autoCompound.toHuman(), null, 2));
} else {
console.log('No auto-compound settings found');
}
process.exit(0);
} catch (error) {
console.error('Error querying at stake:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**autoCompoundingDelegations**(AccountId20) - returns a list of delegators for a given candidate that have set up auto-compounding along with the percentage of rewards set to be auto-compounded"
=== "Parameters"
- `AccountId20` - the collator address to query. If omitted, information about all collators will be returned
=== "Returns"
The list of delegators who have auto-compounding enabled and the respective percentage of rewards they have set to be auto-compounded
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Example candidate address
const candidateAddress = 'INSERT_COLLATOR_ADDRESS';
console.log('Query Parameters:');
console.log('Candidate address:', candidateAddress);
// Query auto-compounding delegations
const autoCompoundDelegations =
await api.query.parachainStaking.autoCompoundingDelegations(
candidateAddress
);
// Get candidate info
const candidateInfo =
await api.query.parachainStaking.candidateInfo(candidateAddress);
if (candidateInfo.isSome) {
const info = candidateInfo.unwrap();
console.log('\nCandidate Information:');
console.log('Total delegations:', info.delegationCount.toString());
console.log('Bond amount:', info.bond.toString());
}
console.log('\nAuto-Compounding Delegations:');
if (autoCompoundDelegations.length > 0) {
console.log(
'Total auto-compounding delegators:',
autoCompoundDelegations.length
);
// Display each auto-compounding delegation
autoCompoundDelegations.forEach((delegation, index) => {
const { delegator, value } = delegation;
console.log(`\nDelegator #${index + 1}:`);
console.log('Address:', delegator.toString());
console.log('Auto-compound percentage:', value.toString(), '%');
});
// Get more detailed information for each delegator
console.log('\nDetailed Delegation Information:');
for (const delegation of autoCompoundDelegations) {
const delegatorState = await api.query.parachainStaking.delegatorState(
delegation.delegator
);
if (delegatorState.isSome) {
const state = delegatorState.unwrap();
const specificDelegation = state.delegations.find(
(d) =>
d.owner.toString().toLowerCase() ===
candidateAddress.toLowerCase()
);
if (specificDelegation) {
console.log(`\nDelegator ${delegation.delegator.toString()}:`);
console.log(
'Delegation amount:',
specificDelegation.amount.toString()
);
console.log(
'Auto-compound value:',
delegation.value.toString(),
'%'
);
}
}
}
// Calculate some statistics
const averageCompounding =
autoCompoundDelegations.reduce(
(acc, curr) => acc + curr.value.toNumber(),
0
) / autoCompoundDelegations.length;
console.log('\nStatistics:');
console.log(
'Average auto-compound percentage:',
averageCompounding.toFixed(2),
'%'
);
const maxCompounding = Math.max(
...autoCompoundDelegations.map((d) => d.value.toNumber())
);
const minCompounding = Math.min(
...autoCompoundDelegations.map((d) => d.value.toNumber())
);
console.log('Highest auto-compound setting:', maxCompounding, '%');
console.log('Lowest auto-compound setting:', minCompounding, '%');
} else {
console.log('No auto-compounding delegations found for this candidate');
}
process.exit(0);
} catch (error) {
console.error('Error querying auto-compounding delegations:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**awardedPts**(u32, AccountId20) - returns the awarded points for each collator per round given a round number and, optionally, the collator's address"
=== "Parameters"
- `u32` - the round number
- `AccountId20` - the collator to query. If omitted, information about all collators will be returned
=== "Returns"
The number of awarded points for a given round and collator.
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get current round information
const round = await api.query.parachainStaking.round();
const currentRound = round.current.toNumber();
// Example collator address - you can set this to null to query all collators
const collatorAddress = 'INSERT_COLLATOR_ADDRESS';
// Query several recent rounds
const roundsToQuery = 5;
const rounds = Array.from(
{ length: roundsToQuery },
(_, i) => currentRound - i
);
console.log('Query Parameters:');
console.log('Current round:', currentRound);
console.log('Collator address:', collatorAddress || 'All collators');
console.log(`Querying last ${roundsToQuery} rounds:`, rounds);
// Store points data for analysis
const pointsData = {};
// Query points for each round
for (const roundNumber of rounds) {
let roundPoints;
if (collatorAddress) {
// Query specific collator
roundPoints = await api.query.parachainStaking.awardedPts(
roundNumber,
collatorAddress
);
console.log(
`\nRound ${roundNumber} Points for ${collatorAddress}:`,
roundPoints.toString()
);
pointsData[roundNumber] = {
[collatorAddress]: roundPoints.toNumber(),
};
} else {
// Query all collators for this round
roundPoints =
await api.query.parachainStaking.awardedPts.entries(roundNumber);
console.log(`\nRound ${roundNumber} Points:`);
pointsData[roundNumber] = {};
for (const [key, points] of roundPoints) {
const collator = key.args[1].toString();
const pointsValue = points.toNumber();
console.log(`Collator ${collator}: ${pointsValue} points`);
pointsData[roundNumber][collator] = pointsValue;
}
}
}
// Calculate statistics
console.log('\nStatistics:');
if (collatorAddress) {
// Statistics for specific collator
const collatorPoints = rounds.map(
(r) => pointsData[r][collatorAddress] || 0
);
const totalPoints = collatorPoints.reduce((a, b) => a + b, 0);
const averagePoints = totalPoints / rounds.length;
const maxPoints = Math.max(...collatorPoints);
const minPoints = Math.min(...collatorPoints);
console.log(`\nCollator ${collatorAddress}:`);
console.log('Total points:', totalPoints);
console.log('Average points per round:', averagePoints.toFixed(2));
console.log('Highest points:', maxPoints);
console.log('Lowest points:', minPoints);
} else {
// Statistics for all collators
const collators = new Set(
rounds.flatMap((r) => Object.keys(pointsData[r]))
);
for (const collator of collators) {
const collatorPoints = rounds.map((r) => pointsData[r][collator] || 0);
const totalPoints = collatorPoints.reduce((a, b) => a + b, 0);
const averagePoints = totalPoints / rounds.length;
const maxPoints = Math.max(...collatorPoints);
const minPoints = Math.min(...collatorPoints);
console.log(`\nCollator ${collator}:`);
console.log('Total points:', totalPoints);
console.log('Average points per round:', averagePoints.toFixed(2));
console.log('Highest points:', maxPoints);
console.log('Lowest points:', minPoints);
console.log('Points history:', collatorPoints.join(', '));
}
}
// Get current selected candidates for context
const selectedCandidates =
await api.query.parachainStaking.selectedCandidates();
console.log('\nCurrently Selected Candidates:', selectedCandidates.length);
console.log(selectedCandidates.map((c) => c.toString()).join('\n'));
process.exit(0);
} catch (error) {
console.error('Error querying awarded points:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**bottomDelegations**(AccountId20) - returns at the most the bottom 50 delegations for all candidates or for a given candidate's address"
=== "Parameters"
- `AccountId20` - the collator to query. If omitted, information about all collators will be returned
=== "Returns"
The bottom 50 delegations for a given collator address
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Example candidate address
const candidateAddress = 'INSERT_COLLATOR_ADDRESS';
// Get candidate info first
const candidateInfo =
await api.query.parachainStaking.candidateInfo(candidateAddress);
console.log('Query Parameters:');
console.log('Candidate address:', candidateAddress);
if (candidateInfo.isSome) {
const info = candidateInfo.unwrap();
console.log('\nCandidate Information:');
console.log('Total delegations:', info.delegationCount.toString());
console.log('Bond amount:', info.bond.toString(), 'Wei');
}
// Query bottom delegations
const bottomDelegations =
await api.query.parachainStaking.bottomDelegations(candidateAddress);
if (bottomDelegations.isSome) {
const delegations = bottomDelegations.unwrap();
console.log('\nBottom Delegations:');
console.log(
'Total bottom delegations found:',
delegations.delegations.length
);
// Sort delegations by amount in descending order
const sortedDelegations = [...delegations.delegations].sort(
(a, b) => BigInt(b.amount) - BigInt(a.amount)
);
// Display each delegation
sortedDelegations.forEach((delegation, index) => {
console.log(`\nDelegation #${index + 1}:`);
console.log('Delegator:', delegation.owner.toString());
console.log('Amount:', delegation.amount.toString(), 'Wei');
// Convert Wei to DEV (1 DEV = 10^18 Wei)
const devAmount = BigInt(delegation.amount) / BigInt(10 ** 18);
console.log('Amount in DEV:', devAmount.toString(), 'DEV');
});
// Calculate some statistics
if (sortedDelegations.length > 0) {
const total = sortedDelegations.reduce(
(acc, curr) => acc + BigInt(curr.amount),
BigInt(0)
);
const average = total / BigInt(sortedDelegations.length);
const highest = sortedDelegations[0].amount;
const lowest = sortedDelegations[sortedDelegations.length - 1].amount;
console.log('\nStatistics:');
console.log('Total delegated in bottom:', total.toString(), 'Wei');
console.log('Average delegation:', average.toString(), 'Wei');
console.log('Highest bottom delegation:', highest.toString(), 'Wei');
console.log('Lowest bottom delegation:', lowest.toString(), 'Wei');
// Show in DEV for readability
console.log('\nStatistics (in DEV):');
console.log(
'Total delegated:',
(BigInt(total) / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log(
'Average delegation:',
(BigInt(average) / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log(
'Highest bottom delegation:',
(BigInt(highest) / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log(
'Lowest bottom delegation:',
(BigInt(lowest) / BigInt(10 ** 18)).toString(),
'DEV'
);
}
// Get top delegations for comparison
const topDelegations =
await api.query.parachainStaking.topDelegations(candidateAddress);
if (topDelegations.isSome) {
const top = topDelegations.unwrap();
console.log('\nComparison with Top Delegations:');
console.log('Number of top delegations:', top.delegations.length);
console.log('Number of bottom delegations:', sortedDelegations.length);
if (top.delegations.length > 0) {
const lowestTop = top.delegations[top.delegations.length - 1].amount;
console.log('Lowest top delegation:', lowestTop.toString(), 'Wei');
console.log(
'Lowest top delegation in DEV:',
(BigInt(lowestTop) / BigInt(10 ** 18)).toString(),
'DEV'
);
}
}
} else {
console.log('\nNo bottom delegations found for this candidate');
}
process.exit(0);
} catch (error) {
console.error('Error querying bottom delegations:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**candidateInfo**(AccountId20) - returns candidate information such as the candidate's bond, delegation count, and more for all candidates or for a given candidate's address"
=== "Parameters"
- `AccountId20` - The collator address to query. If omitted, information about all collators will be returned
=== "Returns"
Information about the relevant collator including collator bond, total backing stake, delegation count, lowest included delegation amount, collator status, and capacity information
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Example candidate address
const candidateAddress = 'INSERT_COLLATOR_ADDRESS';
console.log('Query Parameters:');
console.log('Candidate address:', candidateAddress);
// Query candidate info
const candidateInfo =
await api.query.parachainStaking.candidateInfo(candidateAddress);
if (candidateInfo.isSome) {
const info = candidateInfo.unwrap();
console.log('\nCandidate Information:');
console.log('Bond:', info.bond.toString(), 'Wei');
console.log(
'Bond in DEV:',
(BigInt(info.bond) / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log('Delegation Count:', info.delegationCount.toString());
console.log('Status:', info.status.toString());
console.log(
'Lowest Top Delegation Amount:',
info.lowestTopDelegationAmount.toString(),
'Wei'
);
console.log(
'Lowest Top Delegation in DEV:',
(BigInt(info.lowestTopDelegationAmount) / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log(
'Highest Bottom Delegation Amount:',
info.highestBottomDelegationAmount.toString(),
'Wei'
);
console.log(
'Highest Bottom Delegation in DEV:',
(
BigInt(info.highestBottomDelegationAmount) / BigInt(10 ** 18)
).toString(),
'DEV'
);
console.log(
'Lowest Bottom Delegation Amount:',
info.lowestBottomDelegationAmount.toString(),
'Wei'
);
console.log(
'Lowest Bottom Delegation in DEV:',
(
BigInt(info.lowestBottomDelegationAmount) / BigInt(10 ** 18)
).toString(),
'DEV'
);
console.log('Top Capacity:', info.topCapacity.toString());
console.log('Bottom Capacity:', info.bottomCapacity.toString());
// Get additional context
const round = await api.query.parachainStaking.round();
console.log('\nCurrent Round:', round.current.toString());
// Check if in selected candidates
const selectedCandidates =
await api.query.parachainStaking.selectedCandidates();
const isSelected = selectedCandidates.some(
(c) => c.toString() === candidateAddress
);
console.log('Is Selected Candidate:', isSelected);
// Get top delegations
const topDelegations =
await api.query.parachainStaking.topDelegations(candidateAddress);
if (topDelegations.isSome) {
const top = topDelegations.unwrap();
console.log('\nTop Delegations Count:', top.delegations.length);
console.log('Total Top Delegated:', top.total.toString(), 'Wei');
console.log(
'Total Top Delegated in DEV:',
(BigInt(top.total) / BigInt(10 ** 18)).toString(),
'DEV'
);
}
// Get bottom delegations
const bottomDelegations =
await api.query.parachainStaking.bottomDelegations(candidateAddress);
if (bottomDelegations.isSome) {
const bottom = bottomDelegations.unwrap();
console.log('\nBottom Delegations Count:', bottom.delegations.length);
console.log('Total Bottom Delegated:', bottom.total.toString(), 'Wei');
console.log(
'Total Bottom Delegated in DEV:',
(BigInt(bottom.total) / BigInt(10 ** 18)).toString(),
'DEV'
);
}
// Get auto-compounding delegations
const autoCompounding =
await api.query.parachainStaking.autoCompoundingDelegations(
candidateAddress
);
console.log(
'\nAuto-compounding Delegations Count:',
autoCompounding.length
);
// Calculate some total statistics
const totalStake =
BigInt(info.bond) +
(topDelegations.isSome
? BigInt(topDelegations.unwrap().total)
: BigInt(0)) +
(bottomDelegations.isSome
? BigInt(bottomDelegations.unwrap().total)
: BigInt(0));
console.log('\nTotal Statistics:');
console.log('Total Stake:', totalStake.toString(), 'Wei');
console.log(
'Total Stake in DEV:',
(totalStake / BigInt(10 ** 18)).toString(),
'DEV'
);
// Check recent points (last 3 rounds)
console.log('\nRecent Points:');
const currentRound = round.current.toNumber();
for (let i = 0; i < 3; i++) {
const roundNumber = currentRound - i;
const points = await api.query.parachainStaking.awardedPts(
roundNumber,
candidateAddress
);
console.log(`Round ${roundNumber}: ${points.toString()} points`);
}
} else {
console.log('\nNo candidate information found for this address');
}
process.exit(0);
} catch (error) {
console.error('Error querying candidate info:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**candidatePool**() - returns a list of each of the candidates in the pool and their total backing stake"
=== "Parameters"
None
=== "Returns"
A list of each of the candidates in the pool and their total backing stake
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get current round information
const round = await api.query.parachainStaking.round();
console.log('Current Round:', round.current.toString());
// Query candidate pool
const candidatePool = await api.query.parachainStaking.candidatePool();
console.log('\nCandidate Pool Information:');
console.log('Total Candidates:', candidatePool.length);
// Sort candidates by amount, handling BigInt comparison correctly
const sortedCandidates = [...candidatePool].sort((a, b) => {
const amountA = BigInt(a.amount);
const amountB = BigInt(b.amount);
if (amountA < amountB) return 1;
if (amountA > amountB) return -1;
return 0;
});
// Get selected candidates for comparison
const selectedCandidates =
await api.query.parachainStaking.selectedCandidates();
const selectedSet = new Set(selectedCandidates.map((c) => c.toString()));
// Track total stake in pool
let totalStake = BigInt(0);
// Display each candidate's information
console.log('\nDetailed Candidate Information:');
for (const [index, candidate] of sortedCandidates.entries()) {
const { owner, amount } = candidate;
totalStake += BigInt(amount);
// Get candidate info
const candidateInfo =
await api.query.parachainStaking.candidateInfo(owner);
console.log(`\nCandidate #${index + 1}:`);
console.log('Address:', owner.toString());
console.log('Total Stake:', amount.toString(), 'Wei');
console.log(
'Total Stake in DEV:',
(BigInt(amount) / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log('Is Selected Collator:', selectedSet.has(owner.toString()));
if (candidateInfo.isSome) {
const info = candidateInfo.unwrap();
console.log('Self Bond:', info.bond.toString(), 'Wei');
console.log(
'Self Bond in DEV:',
(BigInt(info.bond) / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log('Delegation Count:', info.delegationCount.toString());
console.log('Status:', info.status.toString());
}
// Get auto-compounding delegations count
const autoCompounding =
await api.query.parachainStaking.autoCompoundingDelegations(owner);
console.log('Auto-compounding Delegations:', autoCompounding.length);
// Get recent points (last 3 rounds)
const currentRound = round.current.toNumber();
let totalPoints = 0;
console.log('Recent Points:');
for (let i = 0; i < 3; i++) {
const roundNumber = currentRound - i;
const points = await api.query.parachainStaking.awardedPts(
roundNumber,
owner
);
console.log(` Round ${roundNumber}: ${points.toString()} points`);
totalPoints += points.toNumber();
}
console.log(
'Average Points (last 3 rounds):',
(totalPoints / 3).toFixed(2)
);
}
// Display pool statistics
console.log('\nPool Statistics:');
console.log('Total Candidates:', candidatePool.length);
console.log('Selected Collators:', selectedCandidates.length);
console.log('Total Stake in Pool:', totalStake.toString(), 'Wei');
console.log(
'Total Stake in Pool (DEV):',
(totalStake / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log(
'Average Stake per Candidate (DEV):',
(totalStake / BigInt(candidatePool.length) / BigInt(10 ** 18)).toString(),
'DEV'
);
// Calculate stake distribution
const stakes = sortedCandidates.map((c) => BigInt(c.amount));
const median = stakes[Math.floor(stakes.length / 2)];
const highest = stakes[0];
const lowest = stakes[stakes.length - 1];
console.log('\nStake Distribution:');
console.log(
'Highest Stake (DEV):',
(highest / BigInt(10 ** 18)).toString()
);
console.log('Median Stake (DEV):', (median / BigInt(10 ** 18)).toString());
console.log('Lowest Stake (DEV):', (lowest / BigInt(10 ** 18)).toString());
process.exit(0);
} catch (error) {
console.error('Error querying candidate pool:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**candidateState**(AccountId20) - *deprecated as of runtime 1200* - use `candidateInfo` instead"
=== "Parameters"
- `AccountId20` - the collator account to query
=== "Returns"
*Deprecated as of runtime 1200* - use `candidateInfo` instead
=== "Polkadot.js API Example"
*Deprecated as of runtime 1200* - use `candidateInfo` instead
??? function "**collatorCommission**() - returns the commission percent taken off of rewards for all collators"
=== "Parameters"
None
=== "Returns"
The percent collator commission, e.g. `20.00%`
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Query collator commission
const commission = await api.query.parachainStaking.collatorCommission();
// Get the current round for context
const round = await api.query.parachainStaking.round();
// Get selected candidates count for context
const selectedCandidates =
await api.query.parachainStaking.selectedCandidates();
console.log('\nCollator Commission Information:');
console.log('Current Round:', round.current.toString());
console.log('Commission Rate:', commission.toString(), 'Per Billion');
// Convert to percentage (commission is stored as parts per billion)
const commissionPercent = (Number(commission) / 10_000_000).toFixed(2);
console.log('Commission Percentage:', commissionPercent + '%');
console.log('\nNetwork Context:');
console.log('Active Collators:', selectedCandidates.length);
// Example calculation for a reward
const exampleReward = BigInt(1000000000000000000); // 1 DEV
const commissionAmount =
(exampleReward * BigInt(commission)) / BigInt(1000000000);
console.log('\nExample Reward Calculation:');
console.log('For a reward of 1 DEV:');
console.log(
'Commission Amount:',
(commissionAmount / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log(
'Remaining Reward:',
((exampleReward - commissionAmount) / BigInt(10 ** 18)).toString(),
'DEV'
);
process.exit(0);
} catch (error) {
console.error('Error querying collator commission:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**collatorState2**(AccountId20) - *deprecated as of runtime 1001* - use `candidateInfo` instead"
=== "Parameters"
- `AccountId20` - the collator to query
=== "Returns"
Deprecated as of runtime 1001* - use `candidateInfo` instead
=== "Polkadot.js API Example"
Deprecated as of runtime 1001* - use `candidateInfo` instead
??? function "**delayedPayouts**(u32) - returns the delayed payouts for all rounds or for a given round"
=== "Parameters"
- `u32` - the round to query. If omitted, the latest round information will be returned
=== "Returns"
The round issuance, the total staking reward, and collator commission.
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get current round information
const round = await api.query.parachainStaking.round();
const currentRound = round.current.toNumber();
console.log('Current Round:', currentRound);
// Query several recent rounds for delayed payouts
const roundsToCheck = 5;
const rounds = Array.from(
{ length: roundsToCheck },
(_, i) => currentRound - i
);
console.log(
'\nChecking Delayed Payouts for the Last',
roundsToCheck,
'Rounds:'
);
// Track statistics
let totalPayouts = 0;
let totalRewards = BigInt(0);
for (const roundNumber of rounds) {
console.log(`\nRound ${roundNumber}:`);
const delayedPayout =
await api.query.parachainStaking.delayedPayouts(roundNumber);
if (delayedPayout.isSome) {
const payout = delayedPayout.unwrap();
// Debug log to see the structure
console.log(
'Raw payout data:',
JSON.stringify(payout.toJSON(), null, 2)
);
// Safely access the data
const payoutData = payout.toJSON();
console.log('Found Delayed Payout:');
if (payoutData) {
totalPayouts++;
// Calculate total rewards if data is available
if (payoutData.colReward && payoutData.delReward) {
const roundReward =
BigInt(payoutData.colReward) + BigInt(payoutData.delReward);
totalRewards += roundReward;
console.log('Collator:', payoutData.toCollator);
console.log('Collator Reward:', payoutData.colReward, 'Wei');
console.log(
'Collator Reward in DEV:',
(BigInt(payoutData.colReward) / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log('Total Delegator Reward:', payoutData.delReward, 'Wei');
console.log(
'Total Delegator Reward in DEV:',
(BigInt(payoutData.delReward) / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log('Total Round Reward:', roundReward.toString(), 'Wei');
console.log(
'Total Round Reward in DEV:',
(roundReward / BigInt(10 ** 18)).toString(),
'DEV'
);
// Get collator information if available
if (payoutData.toCollator) {
const collatorInfo =
await api.query.parachainStaking.candidateInfo(
payoutData.toCollator
);
if (collatorInfo.isSome) {
const info = collatorInfo.unwrap();
console.log('\nCollator Information:');
console.log(
'Delegation Count:',
info.delegationCount.toString()
);
console.log('Self Bond:', info.bond.toString(), 'Wei');
console.log(
'Self Bond in DEV:',
(BigInt(info.bond) / BigInt(10 ** 18)).toString(),
'DEV'
);
}
// Get awarded points for context
const points = await api.query.parachainStaking.awardedPts(
roundNumber,
payoutData.toCollator
);
console.log('Points earned in round:', points.toString());
}
}
}
} else {
console.log('No delayed payout found');
}
}
// Display statistics
console.log('\nPayout Statistics:');
console.log('Total Rounds with Payouts:', totalPayouts);
console.log(
'Average Payouts per Round:',
(totalPayouts / roundsToCheck).toFixed(2)
);
if (totalPayouts > 0) {
console.log(
'Average Reward per Payout:',
(totalRewards / BigInt(totalPayouts) / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log(
'Total Rewards:',
(totalRewards / BigInt(10 ** 18)).toString(),
'DEV'
);
}
process.exit(0);
} catch (error) {
console.error('Error querying delayed payouts:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**delegationScheduledRequests**(AccountId20) - returns the outstanding scheduled delegation requests for all collators or for a given collator's address"
=== "Parameters"
- `AccountId20` - the address of the collator. If omitted, information about all collators will be returned
=== "Returns"
The set of pending scheduled delegation requests including the delegator's address, the action requested, and eligible block at which the action can be executed.
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Example collator address
const collatorAddress = 'INSERT_COLLATOR_ADDRESS';
// Get current round information for context
const round = await api.query.parachainStaking.round();
const currentRound = round.current.toNumber();
console.log('Query Parameters:');
console.log('Collator address:', collatorAddress);
console.log('Current round:', currentRound);
// Get collator info for context
const collatorInfo =
await api.query.parachainStaking.candidateInfo(collatorAddress);
if (collatorInfo.isSome) {
const info = collatorInfo.unwrap();
console.log('\nCollator Information:');
console.log('Delegation Count:', info.delegationCount.toString());
console.log('Current Bond:', info.bond.toString(), 'Wei');
console.log(
'Current Bond in DEV:',
(BigInt(info.bond) / BigInt(10 ** 18)).toString(),
'DEV'
);
}
// Query scheduled delegation requests
const requests =
await api.query.parachainStaking.delegationScheduledRequests(
collatorAddress
);
console.log('\nScheduled Delegation Requests:');
if (requests.length > 0) {
console.log('Total requests:', requests.length);
// Process each request
requests.forEach((request, index) => {
console.log(`\nRequest #${index + 1}:`);
const { delegator, whenExecutable, action } = request;
console.log('Delegator:', delegator.toString());
console.log('Executable at round:', whenExecutable.toString());
console.log(
'Rounds until executable:',
whenExecutable.toNumber() - currentRound
);
// Handle different types of actions
if (action.isDecrease) {
const amount = action.asDecrease;
console.log('Action: Decrease');
console.log('Amount:', amount.toString(), 'Wei');
console.log(
'Amount in DEV:',
(BigInt(amount) / BigInt(10 ** 18)).toString(),
'DEV'
);
} else if (action.isRevoke) {
const amount = action.asRevoke;
console.log('Action: Revoke');
console.log('Amount:', amount.toString(), 'Wei');
console.log(
'Amount in DEV:',
(BigInt(amount) / BigInt(10 ** 18)).toString(),
'DEV'
);
}
});
// Calculate some statistics
let totalDecreaseAmount = BigInt(0);
let totalRevokeAmount = BigInt(0);
let decreaseCount = 0;
let revokeCount = 0;
requests.forEach((request) => {
if (request.action.isDecrease) {
totalDecreaseAmount += BigInt(request.action.asDecrease);
decreaseCount++;
} else if (request.action.isRevoke) {
totalRevokeAmount += BigInt(request.action.asRevoke);
revokeCount++;
}
});
console.log('\nRequest Statistics:');
console.log('Decrease requests:', decreaseCount);
if (decreaseCount > 0) {
console.log(
'Total decrease amount:',
totalDecreaseAmount.toString(),
'Wei'
);
console.log(
'Total decrease amount in DEV:',
(totalDecreaseAmount / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log(
'Average decrease amount in DEV:',
(
totalDecreaseAmount /
BigInt(decreaseCount) /
BigInt(10 ** 18)
).toString(),
'DEV'
);
}
console.log('Revoke requests:', revokeCount);
if (revokeCount > 0) {
console.log(
'Total revoke amount:',
totalRevokeAmount.toString(),
'Wei'
);
console.log(
'Total revoke amount in DEV:',
(totalRevokeAmount / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log(
'Average revoke amount in DEV:',
(
totalRevokeAmount /
BigInt(revokeCount) /
BigInt(10 ** 18)
).toString(),
'DEV'
);
}
// Show impact on collator's delegation
const totalImpact = totalDecreaseAmount + totalRevokeAmount;
console.log('\nTotal Impact:');
console.log('Total amount to be removed:', totalImpact.toString(), 'Wei');
console.log(
'Total amount to be removed in DEV:',
(totalImpact / BigInt(10 ** 18)).toString(),
'DEV'
);
} else {
console.log('No scheduled delegation requests found');
}
process.exit(0);
} catch (error) {
console.error('Error querying delegation requests:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**delegatorState**(AccountId20) - returns delegator information such as their delegations, delegation status, and total delegation amount for all delegators or for a given delegator's address"
=== "Parameters"
- `AccountId20` - the address of the delegator to query
=== "Returns"
Delegator state information including the collators delegated and their respective amounts
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Example delegator address
const delegatorAddress = 'INSERT_DELEGATOR_ADDRESS';
// Get current round information for context
const round = await api.query.parachainStaking.round();
const currentRound = round.current.toNumber();
console.log('Query Parameters:');
console.log('Delegator address:', delegatorAddress);
console.log('Current round:', currentRound);
// Query delegator state
const delegatorState =
await api.query.parachainStaking.delegatorState(delegatorAddress);
if (delegatorState.isSome) {
const state = delegatorState.unwrap();
const delegations = state.delegations;
console.log('\nDelegator Information:');
console.log('Total Delegations:', delegations.length);
// Calculate total delegated amount
let totalDelegated = BigInt(0);
delegations.forEach((d) => {
totalDelegated += BigInt(d.amount);
});
console.log('Total Amount Delegated:', totalDelegated.toString(), 'Wei');
console.log(
'Total Amount Delegated in DEV:',
(totalDelegated / BigInt(10 ** 18)).toString(),
'DEV'
);
// Show detailed delegation information
console.log('\nDetailed Delegations:');
for (const [index, delegation] of delegations.entries()) {
console.log(`\nDelegation #${index + 1}:`);
console.log('Collator:', delegation.owner.toString());
console.log('Amount:', delegation.amount.toString(), 'Wei');
console.log(
'Amount in DEV:',
(BigInt(delegation.amount) / BigInt(10 ** 18)).toString(),
'DEV'
);
// Get collator information
const collatorInfo = await api.query.parachainStaking.candidateInfo(
delegation.owner
);
if (collatorInfo.isSome) {
const info = collatorInfo.unwrap();
console.log('Collator Status:', info.status.toString());
console.log('Collator Total Bond:', info.bond.toString(), 'Wei');
console.log(
'Collator Delegation Count:',
info.delegationCount.toString()
);
}
// Check auto-compound setting
const autoCompoundDelegations =
await api.query.parachainStaking.autoCompoundingDelegations(
delegation.owner
);
const autoCompound = autoCompoundDelegations.find(
(d) =>
d.delegator.toString().toLowerCase() ===
delegatorAddress.toLowerCase()
);
if (autoCompound) {
console.log(
'Auto-compound Percentage:',
autoCompound.value.toString(),
'%'
);
} else {
console.log('Auto-compound: Not set');
}
// Check for scheduled requests
const requests =
await api.query.parachainStaking.delegationScheduledRequests(
delegation.owner
);
const delegatorRequests = requests.filter(
(r) =>
r.delegator.toString().toLowerCase() ===
delegatorAddress.toLowerCase()
);
if (delegatorRequests.length > 0) {
console.log('\nPending Requests:');
delegatorRequests.forEach((request) => {
console.log(
'Executable at round:',
request.whenExecutable.toString()
);
if (request.action.isDecrease) {
console.log('Action: Decrease');
console.log(
'Amount:',
request.action.asDecrease.toString(),
'Wei'
);
console.log(
'Amount in DEV:',
(
BigInt(request.action.asDecrease) / BigInt(10 ** 18)
).toString(),
'DEV'
);
} else if (request.action.isRevoke) {
console.log('Action: Revoke');
console.log('Amount:', request.action.asRevoke.toString(), 'Wei');
console.log(
'Amount in DEV:',
(BigInt(request.action.asRevoke) / BigInt(10 ** 18)).toString(),
'DEV'
);
}
});
}
}
// Calculate statistics
const amounts = delegations.map((d) => BigInt(d.amount));
const averageDelegation = totalDelegated / BigInt(delegations.length);
const maxDelegation = amounts.reduce(
(a, b) => (a > b ? a : b),
BigInt(0)
);
const minDelegation = amounts.reduce(
(a, b) => (a < b ? a : b),
amounts[0] || BigInt(0)
);
console.log('\nDelegation Statistics:');
console.log(
'Average Delegation:',
(averageDelegation / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log(
'Largest Delegation:',
(maxDelegation / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log(
'Smallest Delegation:',
(minDelegation / BigInt(10 ** 18)).toString(),
'DEV'
);
// Get network context
const selectedCandidates =
await api.query.parachainStaking.selectedCandidates();
console.log('\nNetwork Context:');
console.log('Total Selected Collators:', selectedCandidates.length);
console.log(
'Delegating to Selected Collators:',
delegations.filter((d) =>
selectedCandidates.some((c) => c.toString() === d.owner.toString())
).length
);
} else {
console.log('\nNo delegator state found for this address');
}
process.exit(0);
} catch (error) {
console.error('Error querying delegator state:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**enabledMarkingOffline**() - returns a boolean indicating whether or not the marking offline feature for inactive collators is enabled"
=== "Parameters"
None
=== "Returns"
`boolean` - Indicating whether or not the marking offline feature for inactive collators is enabled
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get marking offline status with the correct method name
const isEnabled = await api.query.parachainStaking.enableMarkingOffline();
console.log('Marking Offline Feature Status:', isEnabled.toHuman());
process.exit(0);
} catch (error) {
console.error('Error querying marking offline status:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**inflationConfig**() - returns the inflation configuration"
=== "Parameters"
None
=== "Returns"
A JSON object that contains the minimum, ideal, and maximum inflation parameters in each of the following thresholds: expected, annual, and round.
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Query inflation configuration
const inflationConfig = await api.query.parachainStaking.inflationConfig();
// Get current round info for context
const round = await api.query.parachainStaking.round();
console.log('Current Round:', round.current.toString());
console.log('\nInflation Configuration (Human Readable):');
const config = inflationConfig.toHuman();
console.log(JSON.stringify(config, null, 2));
// Access the nested structure correctly
const rawConfig = inflationConfig.toJSON();
console.log('\nDetailed Configuration Breakdown:');
// Expected rewards
console.log('\nExpected Rewards:');
console.log('Min:', rawConfig.expect.min);
console.log('Ideal:', rawConfig.expect.ideal);
console.log('Max:', rawConfig.expect.max);
// Annual inflation rates (divide by 10^7 to get percentage)
console.log('\nAnnual Inflation Rates:');
console.log('Min:', (rawConfig.annual.min / 10_000_000).toFixed(2) + '%');
console.log(
'Ideal:',
(rawConfig.annual.ideal / 10_000_000).toFixed(2) + '%'
);
console.log('Max:', (rawConfig.annual.max / 10_000_000).toFixed(2) + '%');
// Round inflation rates
console.log('\nRound Inflation Rates:');
console.log('Min:', (rawConfig.round.min / 10_000_000).toFixed(4) + '%');
console.log(
'Ideal:',
(rawConfig.round.ideal / 10_000_000).toFixed(4) + '%'
);
console.log('Max:', (rawConfig.round.max / 10_000_000).toFixed(4) + '%');
// Example calculations for 100 DEV with annual rates
const exampleStake = 100n * BigInt(10 ** 18); // 100 DEV
console.log('\nExample Annual Returns for 100 DEV stake:');
// Convert to BigInt for calculations
const annualMin =
(BigInt(rawConfig.annual.min) * exampleStake) /
BigInt(10_000_000) /
BigInt(10 ** 18);
const annualIdeal =
(BigInt(rawConfig.annual.ideal) * exampleStake) /
BigInt(10_000_000) /
BigInt(10 ** 18);
const annualMax =
(BigInt(rawConfig.annual.max) * exampleStake) /
BigInt(10_000_000) /
BigInt(10 ** 18);
console.log('Min:', annualMin.toString(), 'DEV');
console.log('Ideal:', annualIdeal.toString(), 'DEV');
console.log('Max:', annualMax.toString(), 'DEV');
process.exit(0);
} catch (error) {
console.error('Error querying inflation configuration:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**nominatorState2**(AccountId20) - *deprecated as of runtime 1001* - use `delegatorState` instead"
=== "Parameters"
- `AccountId20` - The account to query
=== "Returns"
Deprecated as of runtime 1001* - use `delegatorState` instead
=== "Polkadot.js API Example"
Deprecated as of runtime 1001* - use `delegatorState` instead
??? function "**palletVersion**() - returns the current pallet version"
=== "Parameters"
None
=== "Returns"
`u16` - current pallet version
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Query pallet version
const version = await api.query.parachainStaking.palletVersion();
console.log('Parachain Staking Pallet Version:', version.toString());
process.exit(0);
} catch (error) {
console.error('Error querying pallet version:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**points**(u32) - returns the total points awarded to collators for block production in all rounds or for a given round"
=== "Parameters"
- `u32` - a round number. If omitted, the data for the last three rounds will be returned
=== "Returns"
- `u32` - total points awarded to collators in the given round
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get current round information
const round = await api.query.parachainStaking.round();
const currentRound = round.current.toNumber();
// Query points for several recent rounds
const roundsToCheck = 5;
const rounds = Array.from(
{ length: roundsToCheck },
(_, i) => currentRound - i
);
console.log('Current Round:', currentRound);
// Get selected candidates for context
const selectedCandidates =
await api.query.parachainStaking.selectedCandidates();
console.log('Number of Selected Collators:', selectedCandidates.length);
// Check each round
for (const roundNumber of rounds) {
console.log(`\nPoints for Round ${roundNumber}:`);
const roundPoints = await api.query.parachainStaking.points(roundNumber);
if (roundPoints.toNumber() === 0) {
console.log('No points recorded for this round');
} else {
console.log('Total Points:', roundPoints.toString());
// Get individual collator points for this round
let collatorPoints = [];
for (const collator of selectedCandidates) {
const points = await api.query.parachainStaking.awardedPts(
roundNumber,
collator
);
if (points.toNumber() > 0) {
collatorPoints.push({
collator: collator.toString(),
points: points.toNumber(),
});
}
}
// Sort collators by points
collatorPoints.sort((a, b) => b.points - a.points);
// Display collator points
if (collatorPoints.length > 0) {
console.log('\nCollator Performance:');
collatorPoints.forEach(({ collator, points }) => {
console.log(`Collator ${collator}: ${points} points`);
});
// Calculate statistics
const totalPoints = collatorPoints.reduce(
(sum, { points }) => sum + points,
0
);
const averagePoints = totalPoints / collatorPoints.length;
const maxPoints = collatorPoints[0].points;
const minPoints = collatorPoints[collatorPoints.length - 1].points;
console.log('\nRound Statistics:');
console.log('Active Collators:', collatorPoints.length);
console.log('Average Points:', averagePoints.toFixed(2));
console.log('Highest Points:', maxPoints);
console.log('Lowest Points:', minPoints);
}
}
}
process.exit(0);
} catch (error) {
console.error('Error querying points:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**round**() - returns the current round number, the first block of the current round, and the length of the round"
=== "Parameters"
None
=== "Returns"
Returns the current round number, the first block of the current round, and the length of the round
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Query round information
const roundInfo = await api.query.parachainStaking.round();
console.log('Round Information:');
console.log('Current Round:', roundInfo.current.toString());
console.log('First Block of Round:', roundInfo.first.toString());
console.log('Round Length:', roundInfo.length.toString());
// Calculate some additional useful information
const currentBlock = await api.rpc.chain.getBlock();
const currentBlockNumber = currentBlock.block.header.number.toNumber();
// Calculate blocks remaining in current round
const blocksIntoRound = currentBlockNumber - roundInfo.first.toNumber();
const blocksRemaining = roundInfo.length.toNumber() - blocksIntoRound;
console.log('\nAdditional Information:');
console.log('Current Block:', currentBlockNumber);
console.log('Blocks Into Current Round:', blocksIntoRound);
console.log('Blocks Remaining in Round:', blocksRemaining);
process.exit(0);
} catch (error) {
console.error('Error querying round information:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**selectedCandidates**() - returns the collator candidates selected to be in the active set for the current round"
=== "Parameters"
None
=== "Returns"
A set of `AccountId20`s - collator candidates selected to be in the active set for the current round
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get current round for context
const round = await api.query.parachainStaking.round();
console.log('Current Round:', round.current.toString());
// Query selected candidates
const selectedCandidates =
await api.query.parachainStaking.selectedCandidates();
console.log('\nSelected Candidates:');
console.log('Total Selected:', selectedCandidates.length);
// Get detailed information for each candidate
console.log('\nDetailed Candidate Information:');
for (const [index, candidate] of selectedCandidates.entries()) {
const candidateInfo =
await api.query.parachainStaking.candidateInfo(candidate);
if (candidateInfo.isSome) {
const info = candidateInfo.unwrap();
console.log(`\nCandidate #${index + 1}:`);
console.log('Address:', candidate.toString());
console.log('Bond:', info.bond.toString(), 'Wei');
console.log(
'Bond in DEV:',
(BigInt(info.bond) / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log('Delegation Count:', info.delegationCount.toString());
console.log('Status:', info.status.toString());
// Get recent points for context (last 3 rounds)
const currentRound = round.current.toNumber();
let recentPoints = 0;
console.log('Recent Points:');
for (let i = 0; i < 3; i++) {
const roundPoints = await api.query.parachainStaking.awardedPts(
currentRound - i,
candidate
);
console.log(` Round ${currentRound - i}: ${roundPoints.toString()}`);
recentPoints += roundPoints.toNumber();
}
console.log('Total Points (last 3 rounds):', recentPoints);
}
}
// Calculate some statistics
let totalBond = BigInt(0);
let totalDelegations = 0;
for (const candidate of selectedCandidates) {
const candidateInfo =
await api.query.parachainStaking.candidateInfo(candidate);
if (candidateInfo.isSome) {
const info = candidateInfo.unwrap();
totalBond += BigInt(info.bond);
totalDelegations += info.delegationCount.toNumber();
}
}
console.log('\nCollective Statistics:');
console.log('Total Bonded:', totalBond.toString(), 'Wei');
console.log(
'Total Bonded in DEV:',
(totalBond / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log(
'Average Bond in DEV:',
(
totalBond /
BigInt(selectedCandidates.length) /
BigInt(10 ** 18)
).toString(),
'DEV'
);
console.log(
'Average Delegations per Candidate:',
(totalDelegations / selectedCandidates.length).toFixed(2)
);
process.exit(0);
} catch (error) {
console.error('Error querying selected candidates:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**topDelegations**(AccountId20) - returns at the most the top 300 delegations for all collators or for a given collator's address"
=== "Parameters"
- `AccountId20` - Address of the given collator. If no address is provided then the top 300 delegations for all collators is returned.
=== "Returns"
Returns up to the top 300 delegations for a given collator, including the address of the delegator and the amount delegated
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Example collator address
const collatorAddress = 'INSERT_COLLATOR_ADDRESS';
// Get collator info first
const candidateInfo =
await api.query.parachainStaking.candidateInfo(collatorAddress);
console.log('Query Parameters:');
console.log('Collator address:', collatorAddress);
if (candidateInfo.isSome) {
const info = candidateInfo.unwrap();
console.log('\nCollator Information:');
console.log('Total delegations:', info.delegationCount.toString());
console.log('Self bond:', info.bond.toString(), 'Wei');
console.log(
'Self bond in DEV:',
(BigInt(info.bond) / BigInt(10 ** 18)).toString(),
'DEV'
);
}
// Query top delegations
const topDelegations =
await api.query.parachainStaking.topDelegations(collatorAddress);
if (topDelegations.isSome) {
const delegations = topDelegations.unwrap();
console.log('\nTop Delegations:');
console.log('Total delegations found:', delegations.delegations.length);
console.log(
'Total amount delegated:',
delegations.total.toString(),
'Wei'
);
console.log(
'Total amount delegated in DEV:',
(BigInt(delegations.total) / BigInt(10 ** 18)).toString(),
'DEV'
);
// Sort delegations by amount in descending order
const sortedDelegations = [...delegations.delegations].sort(
(a, b) => BigInt(b.amount) - BigInt(a.amount)
);
// Display each delegation
console.log('\nDelegation Details:');
sortedDelegations.forEach((delegation, index) => {
console.log(`\nDelegation #${index + 1}:`);
console.log('Delegator:', delegation.owner.toString());
console.log('Amount:', delegation.amount.toString(), 'Wei');
console.log(
'Amount in DEV:',
(BigInt(delegation.amount) / BigInt(10 ** 18)).toString(),
'DEV'
);
});
// Calculate statistics
if (sortedDelegations.length > 0) {
const amounts = sortedDelegations.map((d) => BigInt(d.amount));
const total = amounts.reduce((a, b) => a + b, BigInt(0));
const average = total / BigInt(sortedDelegations.length);
const highest = amounts[0];
const lowest = amounts[amounts.length - 1];
const median = amounts[Math.floor(amounts.length / 2)];
console.log('\nDelegation Statistics:');
console.log(
'Average delegation:',
(average / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log(
'Highest delegation:',
(highest / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log(
'Median delegation:',
(median / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log(
'Lowest delegation:',
(lowest / BigInt(10 ** 18)).toString(),
'DEV'
);
// Distribution analysis
const totalDelegated = BigInt(delegations.total);
console.log('\nStake Distribution:');
console.log(
'Top 5 delegators control:',
(
(amounts.slice(0, 5).reduce((a, b) => a + b, BigInt(0)) *
BigInt(100)) /
totalDelegated
).toString() + '%'
);
if (sortedDelegations.length >= 10) {
console.log(
'Top 10 delegators control:',
(
(amounts.slice(0, 10).reduce((a, b) => a + b, BigInt(0)) *
BigInt(100)) /
totalDelegated
).toString() + '%'
);
}
}
// Check auto-compound settings
const autoCompoundDelegations =
await api.query.parachainStaking.autoCompoundingDelegations(
collatorAddress
);
console.log('\nAuto-compound Settings:');
console.log(
'Delegators with auto-compound:',
autoCompoundDelegations.length
);
} else {
console.log('\nNo top delegations found for this collator');
}
process.exit(0);
} catch (error) {
console.error('Error querying top delegations:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**total**() - returns the total capital locked in the staking pallet"
=== "Parameters"
None
=== "Returns"
`u128` - returns the total capital locked in the staking pallet
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get total staked amount
const totalStaked = await api.query.parachainStaking.total();
console.log('Total Staked:');
console.log('Amount:', totalStaked.toString(), 'Wei');
console.log(
'Amount in DEV:',
(BigInt(totalStaked) / BigInt(10 ** 18)).toString(),
'DEV'
);
// Get some context information
const selectedCandidates =
await api.query.parachainStaking.selectedCandidates();
console.log('\nNetwork Context:');
console.log('Number of Selected Collators:', selectedCandidates.length);
// Get total issuance for percentage calculation
const totalIssuance = await api.query.balances.totalIssuance();
const percentageStaked =
(BigInt(totalStaked) * BigInt(100)) / BigInt(totalIssuance);
console.log('\nStaking Metrics:');
console.log(
'Total Issuance:',
(BigInt(totalIssuance) / BigInt(10 ** 18)).toString(),
'DEV'
);
console.log(
'Percentage of Total Supply Staked:',
percentageStaked.toString() + '%'
);
// Calculate average stake per collator
const averageStakePerCollator =
BigInt(totalStaked) / BigInt(selectedCandidates.length);
console.log(
'Average Stake per Collator:',
(averageStakePerCollator / BigInt(10 ** 18)).toString(),
'DEV'
);
process.exit(0);
} catch (error) {
console.error('Error querying total staked:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**totalSelected**() - returns the total number of collator candidates that can be selected for the active set"
=== "Parameters"
None
=== "Returns"
`u32` - returns the total number of collator candidates that can be selected for the active set
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get total number of collators that can be selected
const totalSelected = await api.query.parachainStaking.totalSelected();
console.log(
'Maximum Number of Collators that can be Selected:',
totalSelected.toString()
);
process.exit(0);
} catch (error) {
console.error('Error querying total selected:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
### Pallet Constants {: #constants }
The parachain staking pallet includes the following read-only functions to obtain pallet constants:
??? function "**candidateBondLessDelay**() - returns the number of rounds that must be waited until a candidate's scheduled request to decrease their self bond can be executed"
=== "Parameters"
None
=== "Returns"
`u32` - returns the number of rounds that must be waited until a candidate's scheduled request to decrease their self bond can be executed
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the bond less delay constant
const delay = await api.consts.parachainStaking.candidateBondLessDelay;
console.log('Candidate Bond Less Delay:', delay.toString(), 'rounds');
process.exit(0);
} catch (error) {
console.error('Error querying candidate bond less delay:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**defaultBlocksPerRound**() - *deprecated as of runtime 1900* - returns the default number of blocks per round"
=== "Parameters"
None
=== "Returns"
*Deprecated as of runtime 1900*
=== "Polkadot.js API Example"
*Deprecated as of runtime 1900*
??? function "**defaultCollatorCommission**() - *deprecated as of runtime 1900* - returns the default commission due to collators"
=== "Parameters"
None
=== "Returns"
*Deprecated as of runtime 1900*
=== "Polkadot.js API Example"
*Deprecated as of runtime 1900*
??? function "**defaultParachainBondReservePercent**() - *deprecated as of runtime 1900* - returns the default percent of inflation set aside for the parachain bond account"
=== "Parameters"
None
=== "Returns"
*Deprecated as of runtime 1900*
=== "Polkadot.js API Example"
*Deprecated as of runtime 1900*
??? function "**delegationBondLessDelay**() - returns the number of rounds that must be waited until a scheduled request to decrease a delegation can be executed"
=== "Parameters"
None
=== "Returns"
`u32` - returns the number of rounds that must be waited until a scheduled request to decrease a delegation can be executed
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the delegation bond less delay constant
const delay = await api.consts.parachainStaking.delegationBondLessDelay;
console.log('Delegation Bond Less Delay:', delay.toString(), 'rounds');
process.exit(0);
} catch (error) {
console.error('Error querying delegation bond less delay:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**leaveCandidatesDelay**() - returns the number of rounds that must be waited before a scheduled request for a candidate to leave the candidate pool can be executed"
=== "Parameters"
None
=== "Returns"
`u32` - returns the number of rounds that must be waited before a scheduled request for a candidate to leave the candidate pool can be executed
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the leaveCandidatesDelay constant from the parachainStaking module
const leaveCandidatesDelay =
await api.consts.parachainStaking.leaveCandidatesDelay;
console.log(
'Leave Candidates Delay:',
leaveCandidatesDelay.toString(),
'rounds'
);
process.exit(0);
} catch (error) {
console.error('Error querying leave candidates delay:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**leaveDelegatorsDelay**() - returns the number of rounds that must be waited before a scheduled request for a delegator to leave the set of delegators can be executed"
=== "Parameters"
None
=== "Returns"
`u32` - returns the number of rounds that must be waited before a scheduled request for a delegator to leave the set of delegators can be executed
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the leaveDelegatorsDelay constant from the parachainStaking module
const leaveDelegatorsDelay =
await api.consts.parachainStaking.leaveDelegatorsDelay;
console.log(
'Leave Delegators Delay:',
leaveDelegatorsDelay.toString(),
'rounds'
);
process.exit(0);
} catch (error) {
console.error('Error querying leave delegators delay:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**linearInflationThreshold**() - returns the total supply threshold at which inflation becomes linear instead of exponential"
=== "Parameters"
None
=== "Returns"
`Option` - returns the total supply threshold at which inflation becomes linear instead of exponential. When the total supply reaches this amount, inflation transitions from exponential to linear. Returns `Some(value)` if configured, or `None` if not set.
Example values are approximately 1.2B DEV for Moonbase, 1.0B MOVR for Moonriver, and 1.2B GLMR for Moonbeam.
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API provider
const wsProvider = new WsProvider('INSERT_WSS_ENDPOINT');
const api = await ApiPromise.create({ provider: wsProvider });
// Get the linear inflation threshold constant
const linearInflationThreshold = api.consts.parachainStaking.linearInflationThreshold;
console.log(`Linear Inflation Threshold: ${linearInflationThreshold.toHuman()}`);
// Disconnect from the API
await api.disconnect();
};
main().catch(console.error);
```
??? function "**maxBottomDelegationsPerCandidate**() - returns the maximum number of bottom delegations per candidate"
=== "Parameters"
None
=== "Returns"
`u32` - returns the maximum number of bottom delegations per candidate
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the maxBottomDelegationsPerCandidate constant from the parachainStaking module
const maxBottomDelegationsPerCandidate =
await api.consts.parachainStaking.maxBottomDelegationsPerCandidate;
console.log(
'Max Bottom Delegations Per Candidate:',
maxBottomDelegationsPerCandidate.toString()
);
process.exit(0);
} catch (error) {
console.error(
'Error querying max bottom delegations per candidate:',
error
);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**maxCandidates**() - returns the maximum number of candidates allowed in the candidate pool"
=== "Parameters"
None
=== "Returns"
`u32` - returns the maximum number of candidates allowed in the candidate pool
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the maximum number of candidates allowed
const maxCandidates = await api.consts.parachainStaking.maxCandidates;
console.log('Maximum Allowed Candidates:', maxCandidates.toString());
process.exit(0);
} catch (error) {
console.error('Error querying max candidates:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**maxDelegationsPerDelegator**() - returns the maximum number of delegations per delegator"
=== "Parameters"
None
=== "Returns"
`u32` - returns the maximum number of delegations per delegator
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the maximum number of delegations per delegator
const maxDelegations =
await api.consts.parachainStaking.maxDelegationsPerDelegator;
console.log(
'Maximum Delegations Per Delegator:',
maxDelegations.toString()
);
process.exit(0);
} catch (error) {
console.error('Error querying max delegations per delegator:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**maxOfflineRounds**() - returns the number of rounds that must pass before a collator that has stopped producing blocks is marked as inactive"
=== "Parameters"
None
=== "Returns"
`u32` - returns the number of rounds that must pass before a collator that has stopped producing blocks is marked as inactive
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the maximum number of offline rounds
const maxOfflineRounds = await api.consts.parachainStaking.maxOfflineRounds;
console.log('Maximum Offline Rounds:', maxOfflineRounds.toString());
process.exit(0);
} catch (error) {
console.error('Error querying max offline rounds:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**maxTopDelegationsPerCandidate**() - returns the maximum number of top delegations per candidate"
=== "Parameters"
None
=== "Returns"
`u32` - returns the maximum number of top delegations per candidate
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the maximum number of top delegations per candidate
const maxTopDelegations =
await api.consts.parachainStaking.maxTopDelegationsPerCandidate;
console.log(
'Maximum Top Delegations Per Candidate:',
maxTopDelegations.toString()
);
process.exit(0);
} catch (error) {
console.error('Error querying max top delegations per candidate:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**minBlocksPerRound**() - returns the minimum number of blocks per round"
=== "Parameters"
None
=== "Returns"
`u32` - returns the minimum number of blocks per round
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the minimum number of blocks per round
const minBlocksPerRound =
await api.consts.parachainStaking.minBlocksPerRound;
console.log('Minimum Blocks Per Round:', minBlocksPerRound.toString());
process.exit(0);
} catch (error) {
console.error('Error querying min blocks per round:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**minCandidateStk**() - returns the minimum stake required for a candidate to be a collator candidate"
=== "Parameters"
None
=== "Returns"
`u128` - returns the minimum stake required for a candidate to be a collator candidate
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the minimum candidate stake required
const minCandidateStake = await api.consts.parachainStaking.minCandidateStk;
console.log(
'Minimum Candidate Stake:',
minCandidateStake.toString(),
'Wei'
);
console.log(
'Minimum Candidate Stake in DEV:',
(BigInt(minCandidateStake) / BigInt(10 ** 18)).toString()
);
process.exit(0);
} catch (error) {
console.error('Error querying min candidate stake:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**minCollatorStk**() - *deprecated as of runtime 2400* - returns the minimum stake required for a candidate to be in the active set"
=== "Parameters"
None
=== "Returns"
*Deprecated as of runtime 2400*
=== "Polkadot.js API Example"
*Deprecated as of runtime 2400*
??? function "**minDelegation**() - returns the minimum delegation amount"
=== "Parameters"
None
=== "Returns"
`u128` - returns the minimum delegation amount
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the minimum delegation amount
const minDelegation = await api.consts.parachainStaking.minDelegation;
console.log('Minimum Delegation Amount:', minDelegation.toString(), 'Wei');
console.log(
'Minimum Delegation Amount in DEV:',
(BigInt(minDelegation) / BigInt(10 ** 18)).toString()
);
process.exit(0);
} catch (error) {
console.error('Error querying min delegation amount:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**minDelegatorStk**() - *deprecated as of runtime 2500* - returns the minimum stake for an account to be a delegator"
=== "Parameters"
None
=== "Returns"
*Deprecated as of runtime 2500*
=== "Polkadot.js API Example"
*Deprecated as of runtime 2500*
??? function "**minSelectedCandidates**() - returns the minimum number of selected candidates in the active set every round"
=== "Parameters"
None
=== "Returns"
`u32` - the minimum number of selected candidates in the active set every round
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the minimum number of selected candidates
const minSelectedCandidates =
await api.consts.parachainStaking.minSelectedCandidates;
console.log(
'Minimum Selected Candidates:',
minSelectedCandidates.toString()
);
process.exit(0);
} catch (error) {
console.error('Error querying min selected candidates:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**revokeDelegationDelay**() - returns the number of rounds that must be waited before a scheduled request to revoke a delegation can be executed"
=== "Parameters"
None
=== "Returns"
`u32` - the number of rounds that must be waited before a scheduled request to revoke a delegation can be executed
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the revoke delegation delay
const revokeDelegationDelay =
await api.consts.parachainStaking.revokeDelegationDelay;
console.log(
'Revoke Delegation Delay:',
revokeDelegationDelay.toString(),
'rounds'
);
process.exit(0);
} catch (error) {
console.error('Error querying revoke delegation delay:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
??? function "**rewardPaymentDelay**() - returns the number of rounds that must be waited after which block authors are rewarded"
=== "Parameters"
None
=== "Returns"
`u32` - The number of rounds that must be waited after which block authors are rewarded
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the reward payment delay
const rewardPaymentDelay =
await api.consts.parachainStaking.rewardPaymentDelay;
console.log(
'Reward Payment Delay:',
rewardPaymentDelay.toString(),
'rounds'
);
process.exit(0);
} catch (error) {
console.error('Error querying reward payment delay:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
```
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/substrate/interfaces/utility/utility/
--- BEGIN CONTENT ---
---
title: Utility Pallet
description: Learn about the available extrinsics for the Utility Pallet on Moonbeam and how to interact with them using Polkadot.js Apps and the Polkadot.js API.
keywords: utility, batch, substrate, pallet, moonbeam, polkadot
categories: Substrate Toolkit
---
# The Utility Pallet
## Introduction {: #introduction }
Through Substrate's Utility Pallet, users on Moonbeam can include multiple calls into a single transaction through the two available batch extrinsics and use derivative accounts to send calls.
This guide will provide an overview and examples of the extrinsics and getters for the pallet constants available in the Utility Pallet on Moonbeam.
## Derivative Accounts {: #derivative-accounts }
Derivative accounts are accounts that are derived from another account using an index. This enables the derivative account to dispatch transactions and use the origin account to pay for transaction fees. Since the private key of this account is unknown, transactions must be initiated with the `asDerivative` extrinsic of this pallet. For example, Alice has a derivative account with an index of `0`. If she transfers any balance using the `asDerivative` function, Alice would still pay for transaction fees, but the funds being transferred will be withdrawn from the derivative account at index `0`.
The derivation is done by calculating the Blake2 hash of `modlpy/utilisuba` + `originalAddress` + `index`. You can use a [script to calculate a derivative account](https://github.com/albertov19/PolkaTools/blob/main/calculateDerivedAddress.ts){target=\_blank} given an origin account and index.
One use case of derivative accounts can be found in the XCM Transactor Pallet. The pallet allows users to perform remote cross-chain calls from an account derived from the Sovereign account, which enables the calls to be easily executed with a simple transaction. For more information, please refer to the [Using the XCM Transactor Pallet for Remote Executions](/builders/interoperability/xcm/remote-execution/substrate-calls/xcm-transactor-pallet/){target=_blank} guide.
## Utility Pallet Interface {: #utility-pallet-interface }
### Extrinsics {: #extrinsics }
The Utility Pallet provides the following extrinsics (functions):
??? function "**asDerivative**(index, call) - sends a call through an indexed pseudonym of the sender"
=== "Parameters"
- `index` - the indexed pseudonym of the sender
- `call` - the encoded call data of the call
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const index = INSERT_INDEX;
const call = 'INSERT_ENCODED_CALL_DATA';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.utility.asDerivative(index, call);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**batch**(calls) - sends a batch of calls to be dispatched. If a call fails, any successful calls up until that point will be processed, and a `BatchInterrupted` event will be emitted. If all calls are successful, then the `BatchCompleted` event is emitted. The number of calls must not exceed the [limit](#constants)"
=== "Parameters"
- `calls` - an array that contains the encoded call data for each of the calls to be dispatched
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const calls = ['INSERT_ENCODED_CALL_DATA'];
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.utility.batch(calls);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**batchAll**(calls) - sends a batch of calls to be dispatched and atomically executes them. If one of the calls fails, the entire transaction will roll back and fail. The number of calls must not exceed the [limit](#constants)"
=== "Parameters"
- `calls` - an array that contains the encoded call data for each of the calls to be dispatched
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const calls = ['INSERT_ENCODED_CALL_DATA'];
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.utility.batchAll(calls);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
??? function "**dispatchAs**(asOrigin, call) - dispatches a function call provided an origin and the call to be dispatched. The dispatch origin for this call must be Root"
=== "Parameters"
- `asOrigin` - the dispatch origin
- `call` - the encoded call data of the call to be dispatched
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const asOrigin = { System: 'Root' };
const call = 'INSERT_ENCODED_CALL_DATA';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.utility.dispatchAs(asOrigin, call);
const txHash = await tx.signAndSend('INSERT_ACCOUNT_OR_KEYRING');
api.disconnect();
};
main();
```
### Pallet Constants {: #constants }
The Utility Pallet includes the following read-only functions to obtain pallet constants:
??? function "**batchedCallsLimit**() - returns the limit on the number of batched calls"
=== "Parameters"
None.
=== "Returns"
The maximum number of calls that can be batched.
```js
// If using Polkadot.js API and calling toJSON() on the query results
10922
```
=== "Polkadot.js API Example"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const batchedCallsLimit = api.consts.utility.batchedCallsLimit;
};
main();
```
## Generating Encoded Call Data {: #generating-encoded-call-data }
To use the extrinsics in the Utility Pallet, you'll need to generate the encoded call data of the call(s) that you're dispatching. You can do this using the Polkadot.js API. You'll assemble the call, and instead of signing and sending it, you'll call `method.toHex()` on the assembled call to get the encoded call data.
For example, to generate the encoded call data of a simple transfer extrinsic, you can use the following code snippet:
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
const api = await ApiPromise.create({
provider: new WsProvider('INSERT_WSS_ENDPOINT'),
});
const tx = api.tx.balances.transferAllowDeath('INSERT_ADDRESS', 'INSERT_AMOUNT');
const encodedCallData = tx.method.toHex();
};
main();
```
You can then pass the `encodedCallData` value into the extrinsic that you're using.
## Using the Batch Extrinsics {: #using-the-batch-extrinsics }
You can access the batch extrinsics using the Polkadot.js Apps interface or through the Polkadot.js API. This example will show you how to use the `batch` extrinsic with Polkadot.js Apps. If you're using the Polkadot.js API, you can access the Utility Pallet through the `api.tx.utility.batch` interface. For more information on batching transactions with the API, please refer to the [Polkadot.js API Library](/builders/substrate/libraries/polkadot-js-api/#batching-transactions){target=_blank} page.
To get started, you can navigate to [Polkadot.js Apps](https://polkadot.js.org/apps/?rpc=wss://wss.api.moonbase.moonbeam.network#/extrinsics){target=\_blank} and connect to Moonbase Alpha. This example can also be adapted for Moonbeam or Moonriver.
You can send any combination of calls, whether they're balance transfers, democracy actions, staking actions, or more.
As a basic example, you can send two balance transfers at once. To get started, click on the **Developer** dropdown, select **Extrinsics**, and take the following steps:
1. Select the account to submit the `batch` extrinsic with
2. Choose **utility** from the **submit the following extrinsic** menu
3. Select the **batch** extrinsic
4. Fields for the first call should already appear, and to add a second call click on **Add item**
5. For the first call, select **balances**
6. Choose the **transfer** extrinsic
7. Enter the destination account to send the funds to
8. Enter an amount of DEV tokens to send in the **value** field, make sure you account for 18 decimals
9. For the second call, you can repeat steps 5 through 8
10. To send the calls at once, click on **Submit Transaction**

Next, you will need to enter your password and click on **Sign and Submit**. Then you can review the extrinsic on [Subscan](https://moonbase.subscan.io/){target=_blank}
!!! note
As a reference, you can [view the exact extrinsic for this example on Subscan](https://moonbase.subscan.io/extrinsic/2561364-6){target=\_blank}.
If you take a look at the **Events** tab at the bottom of the extrinsic page, you should see several events, including two `balances (Transfer)` events, two `utility (ItemCompleted)` events, and a `utility (BatchCompleted)` event containing the details of the batch transaction.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/substrate/libraries/polkadot-js-api/
--- BEGIN CONTENT ---
---
title: How to use the Polkadot.js API
description: Learn how to use the Polkadot.js API to interact with a Moonbeam node to get chain data and send transactions (extrinsics) via the Substrate side of Moonbeam.
categories: Substrate Toolkit, Libraries and SDKs
---
# Polkadot.js API Library
## Introduction {: #introduction }
[Polkadot.js](https://wiki.polkadot.com/general/polkadotjs/){target=\_blank} is a collection of tools that allow you to interact with Polkadot and its parachains, such as Moonbeam. The [Polkadot.js API](https://polkadot.js.org/docs/api/){target=\_blank} is one component of Polkadot.js and is a library that allows application developers to query a Moonbeam node and interact with the node's Substrate interfaces using JavaScript, enabling you to read and write data to the network.
You can use the Polkadot.js API to query on-chain data and send extrinsics from the Substrate side of Moonbeam. You can query Moonbeam's runtime constants, chain state, events, transaction (extrinsic) data, and more.
Here you will find an overview of the available functionalities and some commonly used code examples to get you started on interacting with Moonbeam networks using the Polkadot.js API library.
## Checking Prerequisites {: #checking-prerequisites }
Installing and using Polkadot.js API library requires Node.js to be installed.
You need to install Node.js (for this example, you can use v16.x) and the npm package manager. You can download directly from [Node.js](https://nodejs.org/en/download/package-manager){target=\_blank} or in your terminal:
=== "Ubuntu"
```bash
curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt install -y nodejs
```
=== "MacOS"
```bash
# You can use homebrew (https://docs.brew.sh/Installation)
brew install node
# Or you can use nvm (https://github.com/nvm-sh/nvm)
nvm install node
```
You can verify that everything is installed correctly by querying the version for each package:
```bash
node -v
```
```bash
npm -v
```
To test out the examples in this guide on Moonbeam or Moonriver, you will need to have your own endpoint and API key, which you can get from one of the supported [Endpoint Providers](/builders/get-started/endpoints/){target=\_blank}.
### Install Polkadot.js API {: #installing-polkadot.js-api-library }
First, you need to install the Polkadot.js API library for your project through a package manager such as `yarn`. Install it in your project directory with the following command:
=== "npm"
```bash
npm i @polkadot/api
```
=== "yarn"
```bash
yarn add @polkadot/api
```
The library also includes other core components like Keyring for account management, or some utilities that are used throughout this guide.
## Create an API Provider Instance {: #creating-an-API-provider-instance }
Similar to [Ethereum API libraries](/builders/ethereum/libraries/){target=\_blank}, you must first instantiate an API instance of the Polkadot.js API. Create the `WsProvider` using the WebSocket endpoint of the Moonbeam network you wish to interact with.
To test out the examples in this guide on Moonbeam or Moonriver, you will need to have your own endpoint and API key, which you can get from one of the supported [Endpoint Providers](/builders/get-started/endpoints/){target=\_blank}.
=== "Moonbeam"
```javascript
// Import
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Construct API provider
const wsProvider = new WsProvider('{{ networks.moonbeam.wss_url }}');
const api = await ApiPromise.create({ provider: wsProvider });
// Code goes here
await api.disconnect();
}
main();
```
=== "Moonriver"
```javascript
// Import
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Construct API provider
const wsProvider = new WsProvider('{{ networks.moonriver.wss_url }}');
const api = await ApiPromise.create({ provider: wsProvider });
// Code goes here
await api.disconnect();
}
main();
```
=== "Moonbase Alpha"
```javascript
// Import
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Construct API provider
const wsProvider = new WsProvider('{{ networks.moonbase.wss_url }}');
const api = await ApiPromise.create({ provider: wsProvider });
// Code goes here
await api.disconnect();
}
main();
```
=== "Moonbeam Dev Node"
```javascript
// Import
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Construct API provider
const wsProvider = new WsProvider('{{ networks.development.wss_url }}');
const api = await ApiPromise.create({ provider: wsProvider });
// Code goes here
await api.disconnect();
}
main();
```
### Metadata and Dynamic API Decoration {: #metadata-and-dynamic-api-decoration }
Before diving into the details of performing different tasks via the Polkadot.js API library, it's useful to understand some of the basic workings of the library.
When the Polkadot.js API connects to a node, one of the first things it does is retrieve the metadata and decorate the API based on the metadata information. The metadata effectively provides data in the form of:
```text
api...
```
Where `` can be either:
- `query` - for endpoints to read all the state queries
- `tx` - for endpoints related to transactions
- `rpc` - for endpoints specific to RPC calls
- `consts` - for endpoints specific to runtime constants
And therefore, none of the information contained in the `api.{query, tx, rpc, consts}..` endpoints are hard-coded in the API. This allows parachains like Moonbeam to have custom endpoints through its [pallets](/builders/substrate/interfaces/){target=\_blank} that can be directly accessed via the Polkadot.js API library.
## Query On-Chain Data on Moonbeam {: #querying-for-information }
In this section, you will learn how to query for on-chain information using the Polkadot.js API library.
### Moonbeam Chain State Queries {: #state-queries }
This category of queries retrieves information related to the current state of the chain. These endpoints are generally of the form `api.query..`, where the module and method decorations are generated through metadata. You can see a list of all available endpoints by examining the `api.query` object, for example via:
```javascript
console.log(api.query);
```
Assuming you've [initialized the API](#creating-an-API-provider-instance), here is a code sample for retrieving basic account information given its address :
```javascript
// Define wallet address
const addr = 'INSERT_ADDRESS';
// Retrieve the last timestamp
const now = await api.query.timestamp.now();
// Retrieve the account balance & current nonce via the system module
const { nonce, data: balance } = await api.query.system.account(addr);
console.log(
`${now}: balance of ${balance.free} and a current nonce of ${nonce}`
);
```
??? code "View the complete script"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Construct API provider
const wsProvider = new WsProvider('INSERT_WSS_ENDPOINT');
const api = await ApiPromise.create({ provider: wsProvider });
// Define wallet address
const addr = 'INSERT_ADDRESS';
// Retrieve the last timestamp via the timestamp module
const now = await api.query.timestamp.now();
// Retrieve the account balance & current nonce via the system module
const { nonce, data: balance } = await api.query.system.account(addr);
console.log(
`${now}: balance of ${balance.free} and a current nonce of ${nonce}`
);
// Disconnect the API
await api.disconnect();
};
main();
```
### Moonbeam RPC Queries {: #rpc-queries }
The RPC calls provide the backbone for the transmission of data to and from the node. This means that all API endpoints such as `api.query`, `api.tx` or `api.derive` just wrap RPC calls, providing information in the encoded format as expected by the node. You can see a list of all available endpoints by examining the `api.rpc` object, for example via:
```javascript
console.log(api.rpc);
```
The `api.rpc` interface follows the a similar format to `api.query`, for instance:
```javascript
// Retrieve the chain name
const chain = await api.rpc.system.chain();
// Retrieve the latest header
const lastHeader = await api.rpc.chain.getHeader();
// Log the information
console.log(
`${chain}: last block #${lastHeader.number} has hash ${lastHeader.hash}`
);
```
??? code "View the complete script"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Construct API provider
const wsProvider = new WsProvider('INSERT_WSS_ENDPOINT');
const api = await ApiPromise.create({ provider: wsProvider });
// Retrieve the chain name
const chain = await api.rpc.system.chain();
// Retrieve the latest header
const lastHeader = await api.rpc.chain.getHeader();
// Log the information
console.log(
`${chain}: last block #${lastHeader.number} has hash ${lastHeader.hash}`
);
// Disconnect the API
await api.disconnect();
};
main();
```
### Query Subscriptions {: #query-subscriptions }
The `rpc` API also provide endpoints for subscriptions. You can adapt the previous example to start using subscriptions to listen to new blocks. Note that you need to remove the API disconnect when using subscriptions, to avoid normal closures of the WSS connection.
```javascript
// Retrieve the chain name
const chain = await api.rpc.system.chain();
// Subscribe to the new headers
await api.rpc.chain.subscribeNewHeads((lastHeader) => {
console.log(
`${chain}: last block #${lastHeader.number} has hash ${lastHeader.hash}`
);
});
// Remove await api.disconnect()!
```
The general pattern for `api.rpc.subscribe*` functions is to pass a callback into the subscription function, and this will be triggered on each new entry as they are imported.
Other calls under `api.query.*` can be modified in a similar fashion to use subscription, including calls that have parameters. Here is an example of how to subscribe to balance changes in an account:
```javascript
// Define wallet address
const addr = 'INSERT_ADDRESS';
// Subscribe to balance changes for a specified account
await api.query.system.account(addr, ({ nonce, data: balance }) => {
console.log(
`Free balance is ${balance.free} with ${balance.reserved} reserved and a nonce of ${nonce}`
);
});
// Remove await api.disconnect()!
```
??? code "View the complete script"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Construct API provider
const wsProvider = new WsProvider('INSERT_WSS_ENDPOINT');
const api = await ApiPromise.create({ provider: wsProvider });
// Retrieve the chain name
const chain = await api.rpc.system.chain();
// Subscribe to the new headers
await api.rpc.chain.subscribeNewHeads((lastHeader) => {
console.log(
`${chain}: last block #${lastHeader.number} has hash ${lastHeader.hash}`
);
});
// Define wallet address
const addr = 'INSERT_ADDRESS';
// Subscribe to balance changes for a specified account
await api.query.system.account(addr, ({ nonce, data: balance }) => {
console.log(
`free balance is ${balance.free} with ${balance.reserved} reserved and a nonce of ${nonce}`
);
// Handle API disconnect here if needed
});
};
main();
```
## Create a Keyring for a Moonbeam Account {: #keyrings }
The Keyring object is used for maintaining key pairs, and the signing of any data, whether it's a transfer, a message, or a contract interaction.
### Create a Keyring Instance {: #creating-a-keyring-instance }
You can create an instance by just creating an instance of the Keyring class, and specifying the default type of wallet address used. For Moonbeam networks, the default wallet type should be `ethereum`.
```javascript
// Import the keyring as required
import Keyring from '@polkadot/keyring';
// Create a keyring instance
const keyring = new Keyring({ type: 'ethereum' });
```
### Add an Account to a Keyring {: #adding-accounts }
There are a number of ways to add an account to the keyring instance, including from the mnemonic phrase and from the shortform private key.
=== "From Mnemonic"
```javascript
// Import the required packages
import Keyring from '@polkadot/keyring';
import { u8aToHex } from '@polkadot/util';
import { mnemonicToLegacySeed, hdEthereum } from '@polkadot/util-crypto';
// Import Ethereum account from mnemonic
const keyringECDSA = new Keyring({ type: 'ethereum' });
const mnemonic = 'INSERT_MNEMONIC';
// Define index of the derivation path and the derivation path
const index = 0;
const ethDerPath = "m/44'/60'/0'/0/" + index;
console.log(`Mnemonic: ${mnemonic}`);
console.log(`--------------------------\n`);
// Extract Ethereum address from mnemonic
const alice = keyringECDSA.addFromUri(`${mnemonic}/${ethDerPath}`);
console.log(`Ethereum Derivation Path: ${ethDerPath}`);
console.log(`Derived Ethereum Address from Mnemonic: ${alice.address}`);
// Extract private key from mnemonic
const privateKey = u8aToHex(
hdEthereum(mnemonicToLegacySeed(mnemonic, '', false, 64), ethDerPath)
.secretKey
);
console.log(`Derived Private Key from Mnemonic: ${privateKey}`);
```
=== "From Private Key"
```javascript
// Import the required packages
import Keyring from '@polkadot/keyring';
// Import Ethereum account from mnemonic
const keyringECDSA = new Keyring({ type: 'ethereum' });
const privateKeyInput = 'INSERT_PK';
// Extract address from private key
const alice = keyringECDSA.addFromUri(privateKeyInput);
console.log(`Derived Address from provided Private Key: ${alice.address}`);
```
## Dry Run API {: #dry-run-api }
The Dry Run API is an easy and convenient way to test the integrity of a call without incurring any transaction fees. The Dry Run API can be accessed from the [Runtime Calls](https://polkadot.js.org/apps/?rpc=wss://wss.api.moonbeam.network#/runtime){target=\_blank} tab of the **Developer** section of Polkadot.js Apps. While primarily intended for the [testing of XCM messages](/builders/interoperability/xcm/send-execute-xcm/#test-an-xcm-message-with-the-dry-run-api){target=\_blank}, the Dry Run API can be used to test any arbitrary call.
This method takes the origin and call data as parameters and returns an execution result and additional event data.
```javascript
const testAccount = api.createType(
'AccountId20',
'0x88bcE0b038eFFa09e58fE6d24fDe4b5Af21aa798'
);
const callData =
'0x030088bce0b038effa09e58fe6d24fde4b5af21aa79813000064a7b3b6e00d';
const callDataU8a = hexToU8a(callData);
const result = await api.call.dryRunApi.dryRunCall(
{ system: { Signed: testAccount } },
callDataU8a
);
```
??? code "View the complete script"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { hexToU8a } from '@polkadot/util';
const main = async () => {
try {
// Construct API provider
const wsProvider = new WsProvider('INSERT_WSS_ENDPOINT');
const api = await ApiPromise.create({ provider: wsProvider });
console.log('Connected to the API. Preparing dry run call...');
// Create a test account (you should replace this with an actual account)
const testAccount = api.createType(
'AccountId20',
'0x88bcE0b038eFFa09e58fE6d24fDe4b5Af21aa798'
);
// The call data (replace with your actual call data)
const callData =
'0x030088bce0b038effa09e58fe6d24fde4b5af21aa79813000064a7b3b6e00d'; // Your hex-encoded call data
// Convert hex to Uint8Array
const callDataU8a = hexToU8a(callData);
// Perform the dry run call
const result = await api.call.dryRunApi.dryRunCall(
{ system: { Signed: testAccount } }, // origin
callDataU8a // call
);
console.log(
'Dry run XCM result:',
JSON.stringify(result.toJSON(), null, 2)
);
// Disconnect the API
await api.disconnect();
console.log('Disconnected from the API.');
} catch (error) {
console.error('An error occurred:', error);
}
};
main().catch(console.error);
```
Upon calling the Dry Run API, the method will tell you whether the call would be successful and returns the event data that would be emitted if the call were actually submitted on chain. You can view the initial output of the `dryRunCall` below.
??? code "View the complete output"
```json
Dry run XCM result: {
"ok": {
"executionResult": {
"ok": {
"actualWeight": null,
"paysFee": "Yes"
}
},
"emittedEvents": [],
"localXcm": null,
// Additional data returned here
// Omitted for clarity
```
## Send Transactions on Moonbeam {: #transactions }
Transaction endpoints are exposed on endpoints generally of the form `api.tx..`, where the module and method decorations are generated through metadata. These allow you to submit transactions for inclusion in blocks, be it transfers, interacting with pallets, or anything else Moonbeam supports. You can see a list of all available endpoints by examining the `api.tx` object, for example via:
```javascript
console.log(api.tx);
```
### Send a Transaction {: #sending-basic-transactions }
The Polkadot.js API library can be used to send transactions to the network. For example, assuming you've [initialized the API](#creating-an-API-provider-instance) and a [keyring instance](#creating-a-keyring-instance), you can use the following snippet to send a basic transaction (this code sample will also retrieve the encoded calldata of the transaction as well as the transaction hash after submitting):
```javascript
// Initialize wallet key pairs
const alice = keyring.addFromUri('INSERT_ALICES_PRIVATE_KEY');
const bob = 'INSERT_BOBS_ADDRESS';
// Form the transaction
const tx = await api.tx.balances.transferAllowDeath(bob, 12345n);
// Retrieve the encoded calldata of the transaction
const encodedCalldata = tx.method.toHex();
console.log(`Encoded calldata: ${encodedCallData}`);
// Sign and send the transaction
const txHash = await tx
.signAndSend(alice);
// Show the transaction hash
console.log(`Submitted with hash ${txHash}`);
```
??? code "View the complete script"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import Keyring from '@polkadot/keyring';
const main = async () => {
// Construct API provider
const wsProvider = new WsProvider('INSERT_WSS_ENDPOINT');
const api = await ApiPromise.create({ provider: wsProvider });
// Create a keyring instance (ECDSA)
const keyring = new Keyring({ type: 'ethereum' });
// Initialize wallet key pairs
const alice = keyring.addFromUri('INSERT_ALICES_PRIVATE_KEY');
const bob = 'INSERT_BOBS_ADDRESS';
// Form the transaction
const tx = await api.tx.balances.transferAllowDeath(bob, BigInt(12345));
// Retrieve the encoded calldata of the transaction
const encodedCalldata = tx.method.toHex();
console.log(`Encoded calldata: ${encodedCalldata}`);
// Sign and send the transaction
const txHash = await tx.signAndSend(alice);
// Show the transaction hash
console.log(`Submitted with hash ${txHash}`);
// Disconnect the API
await api.disconnect();
};
main();
```
!!! note
Prior to client v0.35.0, the extrinsic used to perform a simple balance transfer was the `balances.transfer` extrinsic. It has since been deprecated and replaced with the `balances.transferAllowDeath` extrinsic.
Note that the `signAndSend` function can also accept optional parameters, such as the `nonce`. For example, `signAndSend(alice, { nonce: aliceNonce })`. You can use the [sample code from the State Queries](/builders/substrate/libraries/polkadot-js-api/#state-queries){target=\_blank} section to retrieve the correct nonce, including transactions in the mempool.
### Fee Information {: #fees }
The transaction endpoint also offers a method to obtain weight information for a given `api.tx..`. To do so, you'll need to use the `paymentInfo` function after having built the entire transaction with the specific `module` and `method`.
The `paymentInfo` function returns weight information in terms of `refTime` and `proofSize`, which can be used to determine the transaction fee. This is extremely helpful when crafting [remote execution calls via XCM](/builders/interoperability/xcm/remote-execution/){target=\_blank}.
For example, assuming you've [initialized the API](#creating-an-API-provider-instance), the following snippet shows how you can get the weight information for a simple balance transfer between two accounts:
```javascript
// Transaction to get weight information
const tx = api.tx.balances.transferAllowDeath('INSERT_BOBS_ADDRESS', BigInt(12345));
// Get weight info
const { partialFee, weight } = await tx.paymentInfo('INSERT_SENDERS_ADDRESS');
console.log(`Transaction weight: ${weight}`);
console.log(`Transaction fee: ${partialFee.toHuman()}`);
```
??? code "View the complete script"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Construct API provider
const wsProvider = new WsProvider('INSERT_WSS_ENDPOINT');
const api = await ApiPromise.create({ provider: wsProvider });
// Transaction to get weight information
const tx = api.tx.balances.transferAllowDeath('INSERT_BOBS_ADDRESS', BigInt(12345));
// Get weight info
const { partialFee, weight } = await tx.paymentInfo('INSERT_SENDERS_ADDRESS');
console.log(`Transaction weight: ${weight}`);
console.log(`Transaction fee: ${partialFee.toHuman()}`);
// Disconnect the API
await api.disconnect();
};
main();
```
### Transaction Events {: #transaction-events }
Any transaction will emit events, as a bare minimum this will always be either a `system.ExtrinsicSuccess` or `system.ExtrinsicFailed` event for the specific transaction. These provide the overall execution result for the transaction, i.e. execution has succeeded or failed.
Depending on the transaction sent, some other events may however be emitted, for instance for a balance transfer event, this could include one or more `balance.Transfer` events.
The Transfer API page includes an [example code snippet](/learn/core-concepts/transfers-api/#monitor-all-balance-transfers-with-the-substrate-api){target=\_blank} for subscribing to new finalized block headers, and retrieving all `balance.Transfer` events.
### Batch Transactions {: #batching-transactions }
The Polkadot.js API allows transactions to be batch processed via the `api.tx.utility.batch` method. The batched transactions are processed sequentially from a single sender. The transaction fee can be estimated using the `paymentInfo` helper method.
For example, assuming you've [initialized the API](#creating-an-API-provider-instance), a [keyring instance](#creating-a-keyring-instance) and [added an account](#adding-accounts), the following example makes a couple of transfers and also uses the `api.tx.parachainStaking` module to schedule a request to decrease the bond of a specific collator candidate:
```javascript
// Construct a list of transactions to batch
const collator = 'INSERT_COLLATORS_ADDRESS';
const txs = [
api.tx.balances.transferAllowDeath('INSERT_BOBS_ADDRESS', BigInt(12345)),
api.tx.balances.transferAllowDeath('INSERT_CHARLEYS_ADDRESS', BigInt(12345)),
api.tx.parachainStaking.scheduleDelegatorBondLess(collator, BigInt(12345)),
];
// Estimate the fees as RuntimeDispatchInfo, using the signer (either
// address or locked/unlocked keypair)
const info = await api.tx.utility.batch(txs).paymentInfo(alice);
console.log(`Estimated fees: ${info}`);
// Construct the batch and send the transactions
api.tx.utility.batch(txs).signAndSend(alice, ({ status }) => {
if (status.isInBlock) {
console.log(`included in ${status.asInBlock}`);
// Disconnect API here!
}
});
```
??? code "View the complete script"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import Keyring from '@polkadot/keyring';
const main = async () => {
// Construct API provider
const wsProvider = new WsProvider('INSERT_WSS_ENDPOINT');
const api = await ApiPromise.create({ provider: wsProvider });
// Create a keyring instance (ECDSA)
const keyring = new Keyring({ type: 'ethereum' });
// Initialize wallet key pairs
const alice = keyring.addFromUri('INSERT_ALICES_PRIVATE_KEY');
// Construct a list of transactions to batch
const collator = 'INSERT_COLLATORS_ADDRESS';
const txs = [
api.tx.balances.transferAllowDeath('INSERT_BOBS_ADDRESS', BigInt(12345)),
api.tx.balances.transferAllowDeath('INSERT_CHARLEYS_ADDRESS', BigInt(12345)),
api.tx.parachainStaking.scheduleDelegatorBondLess(collator, BigInt(12345)),
];
// Estimate the fees as RuntimeDispatchInfo, using the signer (either
// address or locked/unlocked keypair)
const info = await api.tx.utility.batch(txs).paymentInfo(alice);
console.log(`Estimated fees: ${info}`);
// Construct the batch and send the transactions
api.tx.utility.batch(txs).signAndSend(alice, async ({ status }) => {
if (status.isInBlock) {
console.log(`Included in ${status.asInBlock}`);
// Disconnect the API
await api.disconnect();
}
});
};
main();
```
!!! note
You can check out all of the available functions for the `parachainStaking` module by adding `console.log(api.tx.parachainStaking);` to your code.
## Substrate and Custom JSON-RPC Endpoints {: #substrate-and-custom-json-rpc-endpoints }
RPCs are exposed as a method on a specific module. This means that once available, you can call any RPC via `api.rpc..(...params[])`. This also works for accessing Ethereum RPCs using the Polkadot.js API, in the form of `polkadotApi.rpc.eth.*`.
Some of the methods available through the Polkadot.js API interface are also available as JSON-RPC endpoints on Moonbeam nodes. This section will provide some examples; you can check for a list of exposed RPC endpoints by calling `api.rpc.rpc.methods()` or the `rpc_methods` endpoint listed below.
- **[`methods()`](https://polkadot.js.org/docs/substrate/rpc/#methods-rpcmethods){target=\_blank}**
- **Interface** - `api.rpc.rpc.methods`
- **JSON-RPC** - `rpc_methods`
- **Returns** - The list of RPC methods that are exposed by the node
```bash
curl --location --request POST 'https://rpc.api.moonbase.moonbeam.network' \
--header 'Content-Type: application/json' \
--data-raw '{
"jsonrpc":"2.0",
"id":1,
"method":"rpc_methods",
"params": []
}'
```
- **[`getBlock(hash?: BlockHash)`](https://polkadot.js.org/docs/substrate/rpc/#getblockhash-blockhash-signedblock){target=\_blank}**
- **Interface** - `api.rpc.chain.getBlock`
- **JSON-RPC** - `chain_getBlock`
- **Returns** - The header and body of a block as specified by the block hash parameter
```bash
curl --location --request POST 'https://rpc.api.moonbase.moonbeam.network' \
--header 'Content-Type: application/json' \
--data-raw '{
"jsonrpc":"2.0",
"id":1,
"method":"chain_getBlock",
"params": ["0x870ad0935a27ed8684048860ffb341d469e091abc2518ea109b4d26b8c88dd96"]
}'
```
- **[`getFinalizedHead()`](https://polkadot.js.org/docs/substrate/rpc/#getfinalizedhead-blockhash){target=\_blank}**
- **Interface** `api.rpc.chain.getFinalizedHead`
- **JSON-RPC** `chain_getFinalizedHead`
- **Returns** The block hash of the last finalized block in the canonical chain
```bash
curl --location --request POST '{{ networks.moonbase.rpc_url }}' \
--header 'Content-Type: application/json' \
--data-raw '{
"jsonrpc":"2.0",
"id":1,
"method":"chain_getHeader",
"params": []
}'
```
The [Consensus and Finality page](/learn/core-concepts/consensus-finality/){target=\_blank} has sample code for using the exposed custom and Substrate RPC calls to check the finality of a given transaction.
## Polkadot.js API Utility Functions {: #utilities }
The Polkadot.js API also includes a number of utility libraries for computing commonly used cryptographic primitives and hash functions.
The following example computes the deterministic transaction hash of a raw Ethereum legacy transaction by first computing its RLP ([Recursive Length Prefix](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/){target=\_blank}) encoding, then hashing the result with keccak256.
```javascript
import { encode } from '@polkadot/util-rlp';
import { keccakAsHex } from '@polkadot/util-crypto';
import { numberToHex } from '@polkadot/util';
// Define the raw signed transaction
const txData = {
nonce: numberToHex(1),
gasPrice: numberToHex(21000000000),
gasLimit: numberToHex(21000),
to: '0xc390cC49a32736a58733Cf46bE42f734dD4f53cb',
value: numberToHex(1000000000000000000),
data: '',
v: '0507',
r: '0x5ab2f48bdc6752191440ce62088b9e42f20215ee4305403579aa2e1eba615ce8',
s: '0x3b172e53874422756d48b449438407e5478c985680d4aaa39d762fe0d1a11683',
};
// Extract the values to an array
var txDataArray = Object.keys(txData).map(function (key) {
return txData[key];
});
// Calculate the RLP encoded transaction
var encoded_tx = encode(txDataArray);
// Hash the encoded transaction using keccak256
console.log(keccakAsHex(encoded_tx));
```
You can check the respective [NPM repository page](https://www.npmjs.com/package/@polkadot/util-crypto/v/0.32.19){target=\_blank} for a list of available methods in the `@polkadot/util-crypto` library and their descriptions.
The information presented herein has been provided by third parties and is made available solely for general information purposes. Moonbeam does not endorse any project listed and described on the Moonbeam Doc Website (https://docs.moonbeam.network/). Moonbeam Foundation does not warrant the accuracy, completeness or usefulness of this information. Any reliance you place on such information is strictly at your own risk. Moonbeam Foundation disclaims all liability and responsibility arising from any reliance placed on this information by you or by anyone who may be informed of any of its contents. All statements and/or opinions expressed in these materials are solely the responsibility of the person or entity providing those materials and do not necessarily represent the opinion of Moonbeam Foundation. The information should not be construed as professional or financial advice of any kind. Advice from a suitably qualified professional should always be sought in relation to any particular matter or circumstance. The information herein may link to or integrate with other websites operated or content provided by third parties, and such other websites may link to this website. Moonbeam Foundation has no control over any such other websites or their content and will have no liability arising out of or related to such websites or their content. The existence of any such link does not constitute an endorsement of such websites, the content of the websites, or the operators of the websites. These links are being provided to you only as a convenience and you release and hold Moonbeam Foundation harmless from any and all liability arising from your use of this information or the information provided by any third-party website or service.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/substrate/libraries/py-substrate-interface/
--- BEGIN CONTENT ---
---
title: How to use the Python Substrate Interface
description: Learn the basics of how to use the Python Substrate Interface library to query chain data, send transactions, and more on Moonbeam networks.
categories: Substrate Toolkit, Libraries and SDKs
---
# Python Substrate Interface
## Introduction {: #introduction }
[Python Substrate Interface](https://github.com/polkascan/py-substrate-interface){target=\_blank} library allows application developers to query a Moonbeam node and interact with the node's Polkadot or Substrate features using a native Python interface. Here you will find an overview of the available functionalities and some commonly used code examples to get you started on interacting with Moonbeam networks using Python Substrate Interface.
## Checking Prerequisites {: #checking-prerequisites }
For the examples in this guide, you will need to have the following:
- An account with funds.
You can get DEV tokens for testing on Moonbase Alpha once every 24 hours from the [Moonbase Alpha Faucet](https://faucet.moonbeam.network){target=\_blank}
-
To test out the examples in this guide on Moonbeam or Moonriver, you will need to have your own endpoint and API key, which you can get from one of the supported [Endpoint Providers](/builders/get-started/endpoints/){target=\_blank}
- Have [`pip`](https://pypi.org/project/pip){target=\_blank} installed
!!! note
The examples in this guide assume you have a MacOS or Ubuntu 22.04-based environment and will need to be adapted accordingly for Windows.
### Installing Python Substrate Interface {: #installing-python-substrate-interface }
You can install Python Substrate Interface library for your project through `pip`. Run the following command in your project directory:
```bash
pip install substrate-interface
```
## Creating an API Provider Instance {: #creating-an-API-provider-instance }
Similar to ETH API libraries, you must first instantiate an API instance of Python Substrate Interface API. Create the `WsProvider` using the websocket endpoint of the Moonbeam network you wish to interact with.
To test out the examples in this guide on Moonbeam or Moonriver, you will need to have your own endpoint and API key, which you can get from one of the supported [Endpoint Providers](/builders/get-started/endpoints/){target=\_blank}.
=== "Moonbeam"
```python
# Imports
from substrateinterface import SubstrateInterface
# Construct the API provider
ws_provider = SubstrateInterface(
url="{{ networks.moonbeam.wss_url }}",
)
```
=== "Moonriver"
```python
# Imports
from substrateinterface import SubstrateInterface
# Construct the API provider
ws_provider = SubstrateInterface(
url="{{ networks.moonriver.wss_url }}",
)
```
=== "Moonbase Alpha"
```python
# Imports
from substrateinterface import SubstrateInterface
# Construct the API provider
ws_provider = SubstrateInterface(
url="{{ networks.moonbase.wss_url }}",
)
```
=== "Moonbeam Dev Node"
```python
# Import
from substrateinterface import SubstrateInterface
# Construct the API provider
ws_provider = SubstrateInterface(
url="{{ networks.development.wss_url }}",
)
```
## Querying for Information {: #querying-for-information }
In this section, you will learn how to query for on-chain information of Moonbeam networks using Python Substrate Interface library.
### Accessing Runtime Constants {: #accessing-runtime-constants }
All runtime constants, such as `BlockWeights`, `DefaultBlocksPerRound` and `ExistentialDeposit`, are provided in the metadata. You can use the [`get_metadata_constants`](https://jamdottech.github.io/py-polkadot-sdk/reference/base/#substrateinterface.base.SubstrateInterface.get_metadata_constants){target=\_blank} method to see a list of available runtime constants within Moonbeam network's metadata.
Runtime constants available in the metadata can be queried through the [`get_constant`](https://jamdottech.github.io/py-polkadot-sdk/reference/base/#substrateinterface.base.SubstrateInterface.get_constant){target=\_blank} method.
```python
# Imports
from substrateinterface import SubstrateInterface
# Construct the API provider
ws_provider = SubstrateInterface(
url="{{ networks.moonbase.wss_url }}",
)
# List of available runtime constants in the metadata
constant_list = ws_provider.get_metadata_constants()
print(constant_list)
# Retrieve the Existential Deposit constant on Moonbeam, which is 0
constant = ws_provider.get_constant("Balances", "ExistentialDeposit")
print(constant.value)
```
### Retrieving Blocks and Extrinsics {: #retrieving-blocks-and-extrinsics }
You can retrieve basic information about Moonbeam networks, such as blocks and extrinsics, using the Python Substrate Interface API.
To retrieve a block, you can use the [`get_block`](https://jamdottech.github.io/py-polkadot-sdk/reference/base/#substrateinterface.base.SubstrateInterface.get_block){target=\_blank} method. You can also access extrinsics and their data fields inside a block object, which is simply a Python dictionary.
To retrieve a block header, you can use the [`get_block_header`](https://jamdottech.github.io/py-polkadot-sdk/reference/base/#substrateinterface.base.SubstrateInterface.get_block_header){target=\_blank} method.
```python
# Imports
from substrateinterface import SubstrateInterface
# Construct the API provider
ws_provider = SubstrateInterface(
url="{{ networks.moonbase.wss_url }}",
)
# Retrieve the latest block
block = ws_provider.get_block()
# Retrieve the latest finalized block
block = ws_provider.get_block_header(finalized_only=True)
# Retrieve a block given its Substrate block hash
block_hash = "0xa499d4ebccdabe31218d232460c0f8b91bd08f72aca25f9b25b04b6dfb7a2acb"
block = ws_provider.get_block(block_hash=block_hash)
# Iterate through the extrinsics inside the block
for extrinsic in block["extrinsics"]:
if "address" in extrinsic:
signed_by_address = extrinsic["address"].value
else:
signed_by_address = None
print(
"\nPallet: {}\nCall: {}\nSigned by: {}".format(
extrinsic["call"]["call_module"].name,
extrinsic["call"]["call_function"].name,
signed_by_address,
)
)
```
!!! note
The block hash used in the above code sample is the Substrate block hash. The standard methods in Python Substrate Interface assume you are using the Substrate version of primitives, such as block or tx hashes.
### Subscribing to New Block Headers {: #subscribing-to-new-block-headers }
You can also adapt the previous example to use a subscription based model to listen to new block headers.
```python
# Imports
from substrateinterface import SubstrateInterface
# Construct the API provider
ws_provider = SubstrateInterface(
url="{{ networks.moonbase.wss_url }}",
)
def subscription_handler(obj, update_nr, subscription_id):
print(f"New block #{obj['header']['number']}")
if update_nr > 10:
return {
"message": "Subscription will cancel when a value is returned",
"updates_processed": update_nr,
}
result = ws_provider.subscribe_block_headers(subscription_handler)
```
### Querying for Storage Information {: #querying-for-storage-information }
You can use the [`get_metadata_storage_functions`](https://jamdottech.github.io/py-polkadot-sdk/reference/base/#substrateinterface.base.SubstrateInterface.get_metadata_storage_functions){target=\_blank} to see a list of available storage functions within Moonbeam network's metadata.
Chain states that are provided in the metadata through storage functions can be queried through the [`query`](https://jamdottech.github.io/py-polkadot-sdk/reference/base/#substrateinterface.base.SubstrateInterface.query){target=\_blank} method.
The Substrate system modules, such as `System`, `Timestamp`, and `Balances`, can be queried to provide basic information such as account nonce and balance. The available storage functions are read from the metadata dynamically, so you can also query for storage information on Moonbeam custom modules, such as `ParachainStaking` and `Democracy`, for state information that's specific to Moonbeam.
```python
# Imports
from substrateinterface import SubstrateInterface
# Construct the API provider
ws_provider = SubstrateInterface(
url="{{ networks.moonbase.wss_url }}",
)
# List of available storage functions in the metadata
method_list = ws_provider.get_metadata_storage_functions()
print(method_list)
# Query basic account information
account_info = ws_provider.query(
module="System",
storage_function="Account",
params=["0x578002f699722394afc52169069a1FfC98DA36f1"],
)
# Log the account nonce
print(account_info.value["nonce"])
# Log the account free balance
print(account_info.value["data"]["free"])
# Query candidate pool information from Moonbeam's Parachain Staking module
candidate_pool_info = ws_provider.query(
module="ParachainStaking", storage_function="CandidatePool", params=[]
)
print(candidate_pool_info)
```
## Signing and Transactions {: #signing-and-transactions }
### Creating a Keypair {: #creating-a-keypair }
The keypair object in Python Substrate Interface is used in the signing of any data, whether it's a transfer, a message, or a contract interaction.
You can create a keypair instance from the shortform private key or from the mnemonic. For Moonbeam networks, you also need to specify the `KeypairType` to be `KeypairType.ECDSA`.
```python
# Imports
from substrateinterface import Keypair, KeypairType
# Define the shortform private key
privatekey = bytes.fromhex("INSERT_PRIVATE_KEY_WITHOUT_0X_PREFIX")
# Define the account mnemonic
mnemonic = "INSERT_MNEMONIC"
# Generate the keypair from shortform private key
keypair = Keypair.create_from_private_key(privatekey, crypto_type=KeypairType.ECDSA)
# Generate the keypair from mnemonic
keypair = Keypair.create_from_mnemonic(mnemonic, crypto_type=KeypairType.ECDSA)
```
### Forming and Sending a Transaction {: #forming-and-sending-a-transaction }
The [`compose_call`](https://jamdottech.github.io/py-polkadot-sdk/reference/base/#substrateinterface.base.SubstrateInterface.compose_call){target=\_blank} method can be used to compose a call payload which can be used as an unsigned extrinsic or a proposal.
Then the payload can be signed using a keypair through the [`create_signed_extrinsic`](https://jamdottech.github.io/py-polkadot-sdk/reference/base/#substrateinterface.base.SubstrateInterface.create_signed_extrinsic){target=\_blank} method.
The signed extrinsic can then be submitted using the [`submit_extrinsic`](https://jamdottech.github.io/py-polkadot-sdk/reference/base/#substrateinterface.base.SubstrateInterface.submit_extrinsic){target=\_blank} method.
This method will also return an `ExtrinsicReceipt` object which contains information about the on-chain execution of the extrinsic. If you need to examine the receipt object, you can set the `wait_for_inclusion` to `True` when submitting the extrinsic to wait until the extrinsic is successfully included into the block.
The following sample code will show a complete example for sending a transaction.
```python
# Imports
from substrateinterface import SubstrateInterface, Keypair, KeypairType
from substrateinterface.exceptions import SubstrateRequestException
# Construct the API provider
ws_provider = SubstrateInterface(
url="{{ networks.moonbase.wss_url }}",
)
# Define the shortform private key of the sending account
privatekey = bytes.fromhex("INSERT_PRIVATE_KEY_WITHOUT_0X_PREFIX")
# Generate the keypair
keypair = Keypair.create_from_private_key(privatekey, crypto_type=KeypairType.ECDSA)
# Form a transaction call
call = ws_provider.compose_call(
call_module="Balances",
call_function="transfer_allow_death",
call_params={
"dest": "0x44236223aB4291b93EEd10E4B511B37a398DEE55",
"value": 1 * 10**18,
},
)
# Form a signed extrinsic
extrinsic = ws_provider.create_signed_extrinsic(call=call, keypair=keypair)
# Submit the extrinsic
try:
receipt = ws_provider.submit_extrinsic(extrinsic, wait_for_inclusion=True)
print(
"Extrinsic '{}' sent and included in block '{}'".format(
receipt.extrinsic_hash, receipt.block_hash
)
)
except SubstrateRequestException as e:
print("Failed to send: {}".format(e))
```
### Offline Signing {: #offline-signing }
You can sign transaction payloads or any arbitrary data using a keypair object through the [`sign`](https://jamdottech.github.io/py-polkadot-sdk/reference/keypair/#substrateinterface.keypair.Keypair.sign){target=\_blank} method. This can be used for offline signing of transactions.
1. First, generate the signature payload on an online machine:
```python
# Imports
from substrateinterface import SubstrateInterface
# Construct the API provider
ws_provider = SubstrateInterface(
url="{{ networks.moonbase.wss_url }}",
)
# Construct a transaction call
call = ws_provider.compose_call(
call_module="Balances",
call_function="transfer_allow_death",
call_params={
"dest": "0x44236223aB4291b93EEd10E4B511B37a398DEE55",
"value": 1 * 10**18,
},
)
# Generate the signature payload
signature_payload = ws_provider.generate_signature_payload(call=call)
```
2. On an offline machine, create a keypair with the private key of the sending account, and sign the signature payload:
```python
# Imports
from substrateinterface import Keypair, KeypairType
# Define the signature payload from the offline machine
signature_payload = "INSERT_SIGNATURE_PAYLOAD"
# Define the shortform private key of the sender account
privatekey = bytes.fromhex("INSERT_PRIVATE_KEY_WITHOUT_0X_PREFIX")
# Generate the keypair from shortform private key
keypair = Keypair.create_from_private_key(privatekey, crypto_type=KeypairType.ECDSA)
# Sign the signature_payload
signature = keypair.sign(signature_payload)
```
3. On an online machine, create a keypair with the public key of the sending account, and submit the extrinsic with the generated signature from the offline machine:
```python
# Imports
from substrateinterface import SubstrateInterface, Keypair, KeypairType
# Construct the API provider
ws_provider = SubstrateInterface(
url="{{ networks.moonbase.wss_url }}",
)
# Define the signature from the offline machine
signature_payload = "INSERT_SIGNATURE_PAYLOAD"
# Construct a keypair with the Ethereum style wallet address of the sending account
keypair = Keypair(public_key="INSERT_ADDRESS_WITHOUT_0X", crypto_type=KeypairType.ECDSA)
# Construct the same transaction call that was signed
call = ws_provider.compose_call(
call_module="Balances",
call_function="transfer_allow_death",
call_params={
"dest": "0x44236223aB4291b93EEd10E4B511B37a398DEE55",
"value": 1 * 10**18,
},
)
# Construct the signed extrinsic with the generated signature
extrinsic = ws_provider.create_signed_extrinsic(
call=call, keypair=keypair, signature=signature
)
# Submit the signed extrinsic
result = ws_provider.submit_extrinsic(extrinsic=extrinsic)
# Print the execution result
print(result.extrinsic_hash)
```
## Custom RPC Requests {: #custom-rpc-requests }
You can also make custom RPC requests with the [`rpc_request`](https://jamdottech.github.io/py-polkadot-sdk/reference/base/#substrateinterface.base.SubstrateInterface.rpc_request){target=\_blank} method.
This is particularly useful for interacting with Moonbeam's [Ethereum JSON-RPC](/builders/ethereum/json-rpc/eth-rpc/){target=\_blank} endpoints or Moonbeam's [custom RPC](/builders/ethereum/json-rpc/moonbeam-custom-api/){target=\_blank} endpoints.
The [Consensus and Finality page](/learn/core-concepts/consensus-finality/#checking-tx-finality-with-substrate-libraries){target=\_blank} has examples for using the custom RPC calls through Python Substrate Interface to check the finality of a transaction given its transaction hash.
The information presented herein has been provided by third parties and is made available solely for general information purposes. Moonbeam does not endorse any project listed and described on the Moonbeam Doc Website (https://docs.moonbeam.network/). Moonbeam Foundation does not warrant the accuracy, completeness or usefulness of this information. Any reliance you place on such information is strictly at your own risk. Moonbeam Foundation disclaims all liability and responsibility arising from any reliance placed on this information by you or by anyone who may be informed of any of its contents. All statements and/or opinions expressed in these materials are solely the responsibility of the person or entity providing those materials and do not necessarily represent the opinion of Moonbeam Foundation. The information should not be construed as professional or financial advice of any kind. Advice from a suitably qualified professional should always be sought in relation to any particular matter or circumstance. The information herein may link to or integrate with other websites operated or content provided by third parties, and such other websites may link to this website. Moonbeam Foundation has no control over any such other websites or their content and will have no liability arising out of or related to such websites or their content. The existence of any such link does not constitute an endorsement of such websites, the content of the websites, or the operators of the websites. These links are being provided to you only as a convenience and you release and hold Moonbeam Foundation harmless from any and all liability arising from your use of this information or the information provided by any third-party website or service.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/substrate/libraries/sidecar/
--- BEGIN CONTENT ---
---
title: Using Substrate API Sidecar with Moonbeam
description: Learn how to use Sidecar, a Substrate-based REST service, with Moonbeam-based networks to access blocks, account balances, compute gas used, and more.
categories: Substrate Toolkit, Libraries and SDKs
---
# Using Substrate API Sidecar with Moonbeam
## Introduction {: #introduction }
Substrate API Sidecar allows applications to access blocks, account balance, and other information of Substrate-based blockchains through a REST API. This can be useful for exchanges, wallets or other types of applications that need to keep track of account balance and other state changes on a Moonbeam network. This page will describe how to install and run a Substrate API Sidecar for Moonbeam, and the commonly used API endpoints.
## Installing and Running Substrate API Sidecar {: #installing-and-running-substrate-api-sidecar }
There are multiple ways of installing and running the Substrate API Sidecar. This guide will describe the steps for installing and running it locally through NPM. For running Substrate API Sidecar through Docker, or building and running it from source, please refer to the [Substrate API Sidecar Github Repository](https://github.com/paritytech/substrate-api-sidecar#readme).
### Checking Prerequisites {: #checking-prerequisites }
Running this service locally through NPM requires Node.js to be installed.
You need to install Node.js (for this example, you can use v16.x) and the npm package manager. You can download directly from [Node.js](https://nodejs.org/en/download/package-manager){target=\_blank} or in your terminal:
=== "Ubuntu"
```bash
curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt install -y nodejs
```
=== "MacOS"
```bash
# You can use homebrew (https://docs.brew.sh/Installation)
brew install node
# Or you can use nvm (https://github.com/nvm-sh/nvm)
nvm install node
```
You can verify that everything is installed correctly by querying the version for each package:
```bash
node -v
```
```bash
npm -v
```
### Installing the Substrate API Sidecar {: #installing-the-substrate-api-sidecar }
To install the Substrate API Sidecar service locally in the current directory, run this from the command line:
```bash
npm install @substrate/api-sidecar@{{ networks.moonbase.substrate_api_sidecar.stable_version }}
```
!!! note
If the current folder does not already have a Node.js project structure, you need to manually create the `node_modules` directory by typing `mkdir node_modules`.
Substrate API Sidecar v{{ networks.moonbase.substrate_api_sidecar.stable_version }} is the current stable version that has been tested to work with Moonbeam networks. You can verify the installation was successful by typing from the installation directory root:
```bash
node_modules/.bin/substrate-api-sidecar --version
```
## Setting up the Substrate API Sidecar {: #setting-up-the-substrate-api-sidecar }
In the terminal that Sidecar will run, export the environmental variable for the WS endpoint of the network. Examples:
=== "Moonbeam"
```bash
export SAS_SUBSTRATE_URL=wss://wss.api.moonbeam.network
```
=== "Moonriver"
```bash
export SAS_SUBSTRATE_URL=wss://wss.api.moonriver.moonbeam.network
```
=== "Moonbase Alpha"
```bash
export SAS_SUBSTRATE_URL=wss://wss.api.moonbase.moonbeam.network
```
=== "Moonbeam Dev Node"
```bash
export SAS_SUBSTRATE_URL=ws://127.0.0.1:9944
```
Please reference the [Public Endpoints](/builders/get-started/endpoints/) page for a full list of Moonbeam network endpoints.
After setting the environmental variable, you can use the `echo` command to check that the environmental variable has been set correctly, by typing:
```bash
echo $SAS_SUBSTRATE_URL
```
And it should display the network endpoint you have just set.
## Generating the Types Bundle {: #generating-the-types-bundle }
Moonbeam introduces custom types that differ from the standard Substrate types. For API clients like Substrate API Sidecar to properly understand and decode these custom types, you must provide Substrate API Sidecar with the corresponding custom types bundle for the respective network you're interacting with. Generating and associating the custom types bundle with Substrate API Sidecar is quick.
First, ensure that you installed [Parity's `generate-types-bundle` package](https://github.com/paritytech/generate-type-bundle){target=\_blank}:
```bash
npm install -g @substrate/generate-type-bundle
```
Then, navigate to the following directory within your project:
```bash
cd ./node_modules/@substrate/api-sidecar/build/src/
```
Then, run the following command to generate the types bundle for the respective network:
=== "Moonbeam"
```bash
generate-type-bundle -p . -s moonbeam
```
=== "Moonriver"
```bash
generate-type-bundle -p . -s moonriver
```
=== "Moonbase Alpha"
```bash
generate-type-bundle -p . -s moonbase
```
Note that running subsequent commands will overwrite the existing `typesBundle.json.` You'll then need to set the `SAS_SUBSTRATE_TYPES_BUNDLE` environment variable as shown below. If you've renamed the `typesBundle.json,` ensure you use the correct file name.
```bash
export SAS_SUBSTRATE_TYPES_BUNDLE="./typesBundle.json"
```
After setting the environment variable, you can verify that you set it correctly by using the following `echo` command:
```bash
echo $SAS_SUBSTRATE_TYPES_BUNDLE
```
## Running Substrate API Sidecar {: #running-substrate-api-sidecar }
Navigate back to the root directory of the project:
```bash
cd ../../../../..
```
With the network endpoint environmental variable set, and from the installation directory root, run:
```bash
node_modules/.bin/substrate-api-sidecar
```
If the installation and configuration are successful, you should see this output in the console:
node_modules/.bin/substrate-api-sidecar v0.42.1: Pulling from moonbeamfoundation/moonbeam
SAS:
📦 LOG:
✅ LEVEL: "info"
✅ JSON: false
✅ FILTER_RPC: false
✅ STRIP_ANSI: false
✅ WRITE: false
✅ WRITE_PATH: "/temp/node_modules/@substrate/api-sidecar/build/src/logs"
✅ WRITE_MAX_FILE_SIZE: 5242880
✅ WRITE_MAX_FILES: 5
📦 SUBSTRATE:
✅ URL: "wss://wss.api.moonbeam.network"
✅ TYPES_BUNDLE: undefined
✅ TYPES_CHAIN: undefined
✅ TYPES_SPEC: undefined
✅ TYPES: undefined
📦 EXPRESS:
✅ BIND_HOST: "127.0.0.1"
✅ PORT: 8080
✅ KEEP_ALIVE_TIMEOUT: 5000
2024-05-07 11:29:54 info: Version: 18.0.0
2024-05-07 11:29:55 warn: API/INIT: RPC methods not decorated: eth_getBlockReceipts, moon_isBlockFinalized, moon_isTxFinalized
2024-05-07 11:29:55 warn: API/INIT: moonbeam/3300: Not decorating unknown runtime apis: 0xd0399cd053adda2b/1, 0xa33d43f58731ad84/2, 0xba8173bf23b2e6f8/1
2024-05-07 11:29:55 info: Connected to chain Moonbeam on the moonbeam client at wss://wss.api.moonbeam.network
2024-05-07 11:29:55 info: Listening on http://127.0.0.1:8080/
2024-05-07 11:29:55 info: Check the root endpoint (http://127.0.0.1:8080) to see the available endpoints for the current node
## Substrate API Sidecar Endpoints {: #substrate-api-sidecar-endpoints }
Some of the commonly used Substrate API Sidecar endpoints include:
- **GET /blocks/head** — Get the most recently finalized block. The optional parameter `finalized` can be set to `false` to the get the newest known block, which may not be finalized
- **GET /blocks/head/header** — Get the most recently finalized block header. The optional parameter `finalized` can be set to `false` to the get the newest known block header, which may not be finalized
- **GET /blocks/{blockId}** — Get a block by its height or hash
- **GET /accounts/{accountId}/balance-info** — Get balance information for an account
- **GET /node/version** — Get information about the Substrates node's implementation and versioning
- **GET /runtime/metadata** — Get the runtime metadata in decoded, JSON form.
For a full list of API endpoints available on Substrate API Sidecar, please refer to the [official documentation](https://paritytech.github.io/substrate-api-sidecar/dist).
## EVM Field Mapping in Block JSON Object {: #evm-fields-mapping-in-block-json-object }
Substrate API Sidecar returns Moonbeam blocks as a JSON object. Information related to EVM execution of Moonbeam transactions is under the `extrinsics` top level field, where individual extrinsics are organized numerically as nested JSON objects. The nesting structure is as following:
```text
RESPONSE JSON Block Object:
|--extrinsics
|--{extrinsic_number}
|--method
|--pallet: "ethereum"
|--method: "transact"
|--signature
|--nonce
|--args
|--transaction
|--{transaction_type}
|--hash
|--events
|--{event_number}
|--method
|--pallet: "ethereum"
|--method: "Executed"
|--data
|--0
|--1
|--2
|--3
...
```
Moonbeam EVM transactions can be identify by the `method` field under the current extrinsic object, where it is set to:
```text
{extrinsic_number}.method.pallet = "ethereum"
{extrinsic_number}.method.method = "transact"
```
### Transaction Types and Payload {: #transaction-types-and-payload }
The Moonbeam EVM currently supports three transaction standards: `legacy`, `eip1559`, and `eip2930`. These correspond to the `transaction type` field in the above JSON object diagram. For each transaction type, the transaction payload contains the following fields:
=== "EIP1559"
```text
...
|--eip1559
|--chainId
|--nonce
|--maxPriorityFeePerGas
|--maxFeePerGas
|--gasLimit
|--action
|--value
|--input
|--accessList
|--oddYParity
|--r
|--s
...
```
=== "Legacy"
```text
...
|--legacy
|--nonce
|--gasPrice
|--gasLimit
|--action
|--value
|--input
|--signature
...
```
=== "EIP2930"
```text
...
|--eip2930
|--chainId
|--nonce
|--gasPrice
|--gasLimit
|--action
|--value
|--input
|--accessList
|--oddYParity
|--r
|--s
...
```
For more information on the new [EIP1559](https://eips.ethereum.org/EIPS/eip-1559){target=\_blank} and [EIP2930](https://eips.ethereum.org/EIPS/eip-2930){target=\_blank} transaction types and what each field means, please refer to the respective official Ethereum proposal specs.
### Transaction Field Mappings {: #transaction-field-mappings }
To obtain the EVM sender address, recipient address, and EVM hash of any EVM transaction type, check the `events` field under the current extrinsic object, and identify the event where the `method` field is set to:
```text
{event_number}.method.pallet: "ethereum"
{event_number}.method.method: "Executed"
```
The EVM field mappings are then summarized as the following:
=== "EIP1559"
| EVM Field | Block JSON Field |
|:------------------------:|:----------------------------------------------------------------------------:|
| Chain ID | `extrinsics[extrinsic_number].args.transaction.eip1559.chainId` |
| Nonce | `extrinsics[extrinsic_number].args.transaction.eip1559.nonce` |
| Max priority fee per gas | `extrinsics[extrinsic_number].args.transaction.eip1559.maxPriorityFeePerGas` |
| Max fee per gas | `extrinsics[extrinsic_number].args.transaction.eip1559.maxFeePerGas` |
| Gas limit | `extrinsics[extrinsic_number].args.transaction.eip1559.gasLimit` |
| Access list | `extrinsics[extrinsic_number].args.transaction.eip1559.accessList` |
| Signature | `extrinsics[extrinsic_number].args.transaction.eip1559.oddYParity/r/s` |
| Sender address | `extrinsics[extrinsic_number].events[event_number].data[0]` |
| Recipient address | `extrinsics[extrinsic_number].events[event_number].data[1]` |
| EVM hash | `extrinsics[extrinsic_number].events[event_number].data[2]` |
| EVM execution status | `extrinsics[extrinsic_number].events[event_number].data[3]` |
=== "Legacy"
| EVM Field | Block JSON Field |
|:--------------------:|:----------------------------------------------------------------:|
| Nonce | `extrinsics[extrinsic_number].args.transaction.legacy.nonce` |
| Gas price | `extrinsics[extrinsic_number].args.transaction.legacy.gasPrice` |
| Gas limit | `extrinsics[extrinsic_number].args.transaction.legacy.gasLimit` |
| Value | `extrinsics[extrinsic_number].args.transaction.legacy.value` |
| Signature | `extrinsics[extrinsic_number].args.transaction.legacy.signature` |
| Sender address | `extrinsics[extrinsic_number].events[event_number].data[0]` |
| Recipient address | `extrinsics[extrinsic_number].events[event_number].data[1]` |
| EVM hash | `extrinsics[extrinsic_number].events[event_number].data[2]` |
| EVM execution status | `extrinsics[extrinsic_number].events[event_number].data[3]` |
=== "EIP2930"
| EVM Field | Block JSON Field |
|:--------------------:|:----------------------------------------------------------------------:|
| Chain ID | `extrinsics[extrinsic_number].args.transaction.eip2930.chainId` |
| Nonce | `extrinsics[extrinsic_number].args.transaction.eip2930.nonce` |
| Gas price | `extrinsics[extrinsic_number].args.transaction.eip2930.gasPrice` |
| Gas limit | `extrinsics[extrinsic_number].args.transaction.eip2930.gasLimit` |
| Value | `extrinsics[extrinsic_number].args.transaction.eip2930.value` |
| Access list | `extrinsics[extrinsic_number].args.transaction.eip2930.accessList` |
| Signature | `extrinsics[extrinsic_number].args.transaction.eip2930.oddYParity/r/s` |
| Sender address | `extrinsics[extrinsic_number].events[event_number].data[0]` |
| Recipient address | `extrinsics[extrinsic_number].events[event_number].data[1]` |
| EVM hash | `extrinsics[extrinsic_number].events[event_number].data[2]` |
| EVM execution status | `extrinsics[extrinsic_number].events[event_number].data[3]` |
!!! note
For Substrate transactions, the "Nonce" and "Signature" fields are under `extrinsics[extrinsic_number]`. For EVM transactions, the "Nonce" and "Signature" fields are under `extrinsics[extrinsic_number].args.transaction[transaction_type]`, leaving the "Nonce" and "Signature" under `extrinsics[extrinsic_number]` to be `null`.
A successfully executed EVM transaction will return either `succeed: "Stopped"` or `succeed: "Returned"` under the "EVM Execution Status" field.
### ERC-20 Token Transfers {: #erc-20-token-transfers }
Events emitted by smart contracts such as an ERC-20 token contract deployed on Moonbeam can be decoded from Sidecar block JSON objects. The nesting structure is as following:
```text
RESPONSE JSON Block Object:
|--extrinsics
|--{extrinsic_number}
|--method
|--pallet: "ethereum"
|--method: "transact"
|--signature:
|--nonce:
|--args
|--transaction
|--{transaction_type}
|--hash
|--events
|--{event_number}
|--method
|--pallet: "evm"
|--method: "Log"
|--data
|--0
|-- address
|-- topics
|--0
|--1
|--2
|-- data
...
...
```
Moonbeam ERC-20 token transfers will emit the [`Transfer`](https://eips.ethereum.org/EIPS/eip-20){target=\_blank} event which can be decoded as the following:
| Tx Information | Block JSON Field |
|:-----------------------:|:---------------------------------------------------------------------:|
| ERC-20 contract address | `extrinsics[extrinsic_number].events[event_number].data[0].address` |
| Event signature hash | `extrinsics[extrinsic_number].events[event_number].data[0].topics[0]` |
| Sender address | `extrinsics[extrinsic_number].events[event_number].data[0].topics[1]` |
| Recipient address | `extrinsics[extrinsic_number].events[event_number].data[0].topics[2]` |
| Amount | `extrinsics[extrinsic_number].events[event_number].data[0].data` |
Other events emitted by EVM smart contracts can be decoded in a similar fashion, but the content of the topics and data fields will change depending on the definition of the specific event.
!!! note
The amount transferred is given in Wei and in hexadecimal format.
## Sample Code for Monitoring Native Token Transfers { #sample-code-for-monitoring-native-token-transfers }
The [Transfers API page](/learn/core-concepts/transfers-api/#using-substrate-api-sidecar){target=\_blank} has a code snippet demonstrating how to use Substrate API Sidecar to retrieve and decode native token transfers sent with both Substrate and Ethereum APIs on Moonbeam networks. You can reference that as a starting point to build out backends that utilize Sidecar to listen to transfers on Moonbeam networks.
## Calculating Transaction Fees {: #calculating-transaction-fees }
For more detailed information and sample code on how to calculate the transaction fees of Moonbeam transactions using Substrate Sidecar API, please check the [Calculating Transaction Fees on Moonbeam](/learn/core-concepts/tx-fees/){target=\_blank} page.
The information presented herein has been provided by third parties and is made available solely for general information purposes. Moonbeam does not endorse any project listed and described on the Moonbeam Doc Website (https://docs.moonbeam.network/). Moonbeam Foundation does not warrant the accuracy, completeness or usefulness of this information. Any reliance you place on such information is strictly at your own risk. Moonbeam Foundation disclaims all liability and responsibility arising from any reliance placed on this information by you or by anyone who may be informed of any of its contents. All statements and/or opinions expressed in these materials are solely the responsibility of the person or entity providing those materials and do not necessarily represent the opinion of Moonbeam Foundation. The information should not be construed as professional or financial advice of any kind. Advice from a suitably qualified professional should always be sought in relation to any particular matter or circumstance. The information herein may link to or integrate with other websites operated or content provided by third parties, and such other websites may link to this website. Moonbeam Foundation has no control over any such other websites or their content and will have no liability arising out of or related to such websites or their content. The existence of any such link does not constitute an endorsement of such websites, the content of the websites, or the operators of the websites. These links are being provided to you only as a convenience and you release and hold Moonbeam Foundation harmless from any and all liability arising from your use of this information or the information provided by any third-party website or service.
--- END CONTENT ---
## Basics Concepts [shared: true]
The following section contains foundational documentation shared across all Moonbeam products.
It describes the architecture and infrastructure that serve as the backbone for all integrations built with Moonbeam.
This includes the network development framework, Substrate and EVM development tools, developer tooling, and guidance for node operators.
This context is provided to help understand how the system works under the hood, but responses should stay focused on the specific product unless the user explicitly asks about the general architecture.
---
## List of shared concept pages:
## Full content for shared concepts:
Doc-Content: https://docs.moonbeam.network/learn/core-concepts/balances/
--- BEGIN CONTENT ---
---
title: Account Balances
description: A description of the main differences that Ethereum developers need to understand in terms of account balances on Moonbeam and how they differ from Ethereum.
categories: Basics
---
# Moonbeam Account Balances
## Introduction {: #introduction }
While Moonbeam strives to be compatible with Ethereum's Web3 API and EVM, there are some important Moonbeam differences that developers should know and understand in terms of account balances.
One of the design goals of Moonbeam is to create an environment that is as close as possible to Ethereum, and to offer a set of Web3 RPC endpoints that are compatible with Ethereum. However, Moonbeam is also a Substrate based chain, which means that it exposes Substrate RPCs, and that it has integral functionality that is powered by Substrate such as Staking, Governance, and other features which are not part of the Ethereum API.
Moonbeam [unified accounts](/learn/core-concepts/unified-accounts/){target=\_blank} are one way that Moonbeam achieves Ethereum compatibility, by changing the underlying account type in the protocol to be Ethereum-like (H160 or 20 byte addresses starting with `0x`). Unified accounts are used by both the Substrate and Ethereum APIs, and map to the same underlying data storage on the blockchain. Nevertheless, there are important differences that users coming from Ethereum should understand when using Moonbeam accounts via the Ethereum API.
This guide will outline some of these main differences and what to expect when using Moonbeam for the first time.
## Ethereum Account Balances {: #ethereum-account-balances }
An account on Ethereum is an entity with a token balance (Ether or ETH in this case). Account-holders can send Ether transactions on Ethereum and accounts can be controlled by either users (with the private key for signing) or smart contracts.
Therefore, Ethereum has two main types of accounts: user-owned and contract-owned. No matter the type, an Ethereum account has a single balance field that represents the number of Wei owned by this address, where Wei is a denomination of ETH (1 x 10^18 Wei per ETH).

## Moonbeam Account Balances {: #moonbeam-account-balances }
An account on Moonbeam is also an entity with a token balance (the token will depend on the network). Like on Ethereum, account holders can send token transactions on the Moonbeam Network they are connected to. In addition, accounts can be controlled by users (with the private key for signing) or smart contracts.
As with Ethereum, there are two main types of accounts: user-owned and contract owned. However, on Moonbeam, within both account types, there are also [proxy accounts](https://wiki.polkadot.com/learn/learn-proxies/){target=\_blank}, which can perform a limited number of actions on behalf of another account. In terms of balances, all of Moonbeam account types have five (5) different [balance types](https://wiki.polkadot.com/learn/learn-accounts/#balance-types#balance-types){target=\_blank}:
- **Free** — refers to the balance that can be used (not locked/frozen) from the Substrate API. The concept of `free` balance depends on the action to be executed. For example, voting in democracy will not subtract the allocated balance to the vote from `free` balance, but token holders won't be able to transfer that balance
- **Reducible** — refers to the balance that can be used (not locked/frozen) through the Ethereum API on Moonbeam. For example, this is the balance displayed by MetaMask. It is the real spendable balance, accounting for all democracy locks (displayed as transferable in Polkadot.js Apps)
- **Reserved** — refers to the balance held due to on-chain requirements, and that can be freed by performing some on-chain action. For example, bonds for creating a proxy account or setting an on-chain identity are shown as `reserved balance`. These funds are **not** transferable or accessible via the Ethereum API until they are freed
- **Misc frozen** — represents a balance that the `free` balance may not drop below when withdrawing funds, except for transaction fee payment. For example, funds being used to vote on a governance proposal are shown as `misc frozen`. These funds are **not** transferable or accessible via the Ethereum API until they are freed
- **Fee frozen** — represents a balance that the `free` balance may not drop below when specifically paying for transaction fees. These funds are **not** transferable or accessible via the Ethereum API until they are freed

### Calculating Your Transferable Balance {: #calculating-your-transferable-balance }
An account's transferable or spendable balance can be calculated as the free balance minus the maximum of `0` or the difference between frozen and reserved tokens:
```text
Transferable = free - max(0, frozen - reserved )
```
Here are two examples of calculating transferable balances:
An account has `1000` free tokens, `200` frozen tokens, and `50` reserved tokens. The transferable balance is calculated as:
```text
Transferable = 1000 - max(0, 200 - 50) = 1000 - 150 = 850
```
If the frozen tokens are less than the reserved tokens, with `1000` free tokens, `100` frozen tokens, and `150` reserved tokens, the transferable balance would be:
```text
Transferable = 1000 - max(0, 100 - 150) = 1000 - 0 = 1000
```
### Retrieve Your Balance {: #retrieve-your-balance }
You can check on your balances, including your free (or transferable) and reserved balances (if exists), using the [Polkadot.js API](/builders/substrate/libraries/polkadot-js-api/){target=\_blank}.
!!! note
To test out the examples in this guide on Moonbeam or Moonriver, you will need to have your own endpoint and API key, which you can get from one of the supported [Endpoint Providers](/builders/get-started/endpoints/){target=\_blank}.
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const wsProvider = new WsProvider('wss://wss.api.moonbase.moonbeam.network');
const main = async () => {
const polkadotApi = await ApiPromise.create({
provider: wsProvider,
});
const balances = await polkadotApi.query.system.account('INSERT_ADDRESS');
console.log(balances.toHuman());
};
main();
```
You can also retrieve your balance locks using the Polkadot.js API.
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const wsProvider = new WsProvider('wss://wss.api.moonbase.moonbeam.network');
const main = async () => {
const polkadotApi = await ApiPromise.create({
provider: wsProvider,
});
const locks = await polkadotApi.query.balances.locks('INSERT_ADDRESS');
console.log(locks.toHuman());
};
main();
```
## Main Differences {: #main-differences }
The main difference between account balances on Ethereum and Moonbeam lies in the concept of locked and reserved balance on Moonbeam. These are tokens that are still owned by that account, but they are not spendable (yet).
From the Ethereum's API perspective, an account might show that it has a certain balance (called `reducible` balance). However, after an on-chain action, this value might increase (or decrease) without an actual balance transfer.
It is important to note that the account and behavior differences described here apply to account balances with the base asset (GLMR, MOVR) only and the balances of that asset that aren't interacting with smart contracts. As soon as a Moonbeam account balance is interacting with smart contracts, the behavior will be the same as Ethereum behavior. For example, if you wrap MOVR on Moonriver there is no way for the underlying balance to change via staking or governance actions, because that is part of the storage of the contract. In this case the reducible balance of that account has been committed to the wrapped MOVR smart contract and can't be modified by Substrate actions.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/core-concepts/consensus-finality/
--- BEGIN CONTENT ---
---
title: Consensus & Finality
description: The main differences that Ethereum developers should understand in terms of consensus and finality on Moonbeam and how it differs from Ethereum.
categories: Basics
---
# Moonbeam Consensus & Finality
## Introduction {: #introduction }
While Moonbeam strives to be compatible with Ethereum's Web3 API and EVM, there are some important Moonbeam differences that developers should know and understand in terms of consensus and finality.
In short, consensus is a way for different parties to agree on a shared state. As blocks are created, nodes in the network must decide which block will represent the next valid state. Finality defines when that valid state cannot be altered or reversed.
Ethereum began by using a consensus protocol based on [Proof-of-Work (PoW)](https://ethereum.org/en/developers/docs/consensus-mechanisms/pow){target=\_blank}, which provides probabilistic finality. However, in 2022, Ethereum switched to [Proof-of-Stake (PoS)](https://ethereum.org/en/developers/docs/consensus-mechanisms/pos){target=\_blank}, which provides deterministic finality, and no longer uses PoW. In contrast, Moonbeam uses a hybrid consensus protocol based on Delegated Proof-of-Stake (DPoS), which also provides deterministic finality. DPoS is an evolution of Polkadot's [Nominated Proof of Stake (NPoS)](https://docs.polkadot.com/polkadot-protocol/architecture/polkadot-chain/pos-consensus/){target=\_blank} concept, that puts more power into the hands of token holders by allowing delegators to choose which collator candidate they want to support and in what magnitude.
This guide will outline some of these main differences around consensus and finality, and what to expect when using Moonbeam for the first time.
## Ethereum Consensus and Finality {: #ethereum-consensus-and-finality }
Ethereum currently uses a PoS consensus protocol, in which validators stake ETH in the network and are responsible for producing blocks and checking the validity of new blocks. The timing of block production is fixed and is divided into 12 second slots and 32 slot epochs. One validator per slot is randomly selected to produce a block and broadcast it to the network. There is a randomly selected committee of validators per slot that is responsible for determining the validity of the block. The greater the stake in the network, the greater the chance the validator will be chosen to produce or validate a block.
Finality is deterministic in Ethereum's PoS consensus protocol and is achieved through "checkpoint" blocks. Validators agree on the state of a block at particular checkpoint blocks, which are always the first block in an epoch, and if two-thirds of the validators agree, the block is finalized. Block finality can be reverted; however, there are strong economic incentives in place so validators do not attempt to collude to revert a block. You can find out more information in Vitalik's [On Settlement Finality](https://blog.ethereum.org/2016/05/09/on-settlement-finality){target=\_blank} blog, under the Finality in Casper section.
## Moonbeam Consensus and Finality {: #moonbeam-consensus-and-finality }
In Polkadot, there are collators and validators. [Collators](https://wiki.polkadot.com/learn/learn-collator/){target=\_blank} maintain parachains (in this case, Moonbeam) by collecting transactions from users and producing state transition proofs for the relay chain [validators](https://wiki.polkadot.com/learn/learn-validator/){target=\_blank}. The collator set (nodes that produce blocks) is selected based on the [stake they have in the network](/learn/features/consensus/){target=\_blank}.
For finality, Polkadot and Kusama rely on [GRANDPA](https://docs.polkadot.com/polkadot-protocol/architecture/polkadot-chain/pos-consensus/#finality-gadget-grandpa){target=\_blank}. GRANDPA provides deterministic finality for any given transaction (block). In other words, when a block or transaction is marked as final, it can't be reverted except via on-chain governance or forking. Moonbeam follows this deterministic finality.
## Main Differences Between PoS and DPoS {: #main-differences }
In terms of consensus, Moonbeam is based on Delegated Proof-of-Stake, while Ethereum relies on a standard Proof-of-Stake system, which is slightly different. Although both mechanisms rely on the use of stake to validate and create new blocks, there are some key differences.
With PoS on Ethereum, validators are selected to produce and validate blocks based on their own stake in the network. As long as a validator has placed a validator deposit, they can be selected to produce and validate blocks. However, as previously mentioned, the greater the stake in the network, the higher the chances a validator has to be selected to produce and validate blocks.
On the other hand, with DPoS on Moonbeam, collators become eligible to produce blocks based on their own stake plus their delegated stake in the network. Any token holder can choose to delegate their stake to a collator candidate. The top collator candidates by stake, including delegations, join the active set. The number of candidates in the active set is subject to [governance](/learn/features/governance/){target=\_blank}. Once in the active set, collators are randomly selected to produce blocks using the [Nimbus Consensus Framework](/learn/features/consensus/){target=\_blank}. It is important to note that once a collator is in the active set, their total stake does not impact their chances of being selected to produce blocks.
In terms of finality, blocks on Ethereum can take quite a bit longer to finalize than on Moonbeam due to the checkpoint finality system it uses. In Ethereum, validators determine finality at checkpoint blocks, which are always the first block in an epoch. Since an epoch has 32 slots and each slot is 12 seconds, it'll take at least 384 seconds, or 6.4 minutes for a block to be finalized.
Moonbeam does not use checkpoint blocks and instead relies on Polkadot's GRANDPA finality gadget, where the finality process is completed in parallel to block production. In addition, the finality process incorporates the blockchain's structure, which allows the relay chain validators to vote on the highest block that they think is valid. In this scenario, the vote would apply to all of the blocks leading up to the one that is finalized, which speeds up the finalization process. After a block has been included in the relay chain, a block can be finalized within one block on Moonbeam.
## Check Transaction Finality with Ethereum RPC Endpoints {: #check-tx-finality-with-ethereum-rpc-endpoints }
Although the finality gadgets differ, you can use the same, fairly simple strategy to check for transaction finality on both Ethereum and Moonbeam:
1. You ask the network for the hash of the latest finalized block
2. You retrieve the block number using the hash
3. You compare it with the block number of your transaction. If your transaction was included in a previous block, it is finalized
4. As a safety check, retrieve the block by number and verify that the given transaction hash is in the block
The snippets below follow this strategy to check transaction finality. It uses the `finalized` option for the [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\_blank} to get the latest finalized block.
To test out the examples in this guide on Moonbeam or Moonriver, you will need to have your own endpoint and API key, which you can get from one of the supported [Endpoint Providers](/builders/get-started/endpoints/){target=\_blank}.
!!! note
The code snippets presented in the following sections are not meant for production environments. Please make sure you adapt it for each use-case.
=== "Ethers.js"
```js
import { ethers } from 'ethers';
// Define the transaction hash to check finality
const txHash = 'INSERT_TX_HASH';
// Define the RPC of the provider for Moonbeam
// This can be adapted for Moonriver or Moonbase Alpha
const providerRPC = {
moonbeam: {
name: 'moonbeam',
rpc: 'INSERT_RPC_API_ENDPOINT',
chainId: 1284,
}
};
// Define the Web3 provider
const web3Provider = new ethers.JsonRpcProvider(providerRPC.moonbeam.rpc, {
chainId: providerRPC.moonbeam.chainId,
name: providerRPC.moonbeam.name,
});
const main = async () => {
// Get the last finalized block
const finalizedBlockHeader = await web3Provider.getBlock('finalized');
const finalizedBlockNumber = finalizedBlockHeader.number;
// Get the transaction receipt of the given transaction hash
const txReceipt = await web3Provider.getTransactionReceipt(txHash);
// If block number of receipt is not null, compare it against finalized head
if (txReceipt) {
const txBlockNumber = txReceipt.blockNumber;
// As a safety check, get given block to check if transaction is included
const txBlock = await web3Provider.getBlock(txBlockNumber);
console.log(`Current finalized block number is ${finalizedBlockNumber}`);
console.log(
`Your transaction in block ${txBlockNumber} is finalized? ${
finalizedBlockNumber >= txBlockNumber
}`
);
console.log(
`Your transaction is indeed in block ${txBlockNumber}? ${txBlock.transactions.includes(
txHash
)}`
);
} else {
console.log(
'Your transaction has not been included in the canonical chain'
);
}
};
main();
```
=== "Web3.js"
```js
import { Web3 } from 'web3';
// Define the transaction hash to check finality
const txHash = 'INSERT_TX_HASH';
// Define the Web3 provider for Moonbeam
// This can be adapted for Moonriver or Moonbase Alpha
const web3Provider = new Web3('INSERT_RPC_API_ENDPOINT');
const main = async () => {
// Get the last finalized block
const finalizedBlockHeader = await web3Provider.eth.getBlock('finalized');
const finalizedBlockNumber = finalizedBlockHeader.number;
// Get the transaction receipt of the given transaction hash
const txReceipt = await web3Provider.eth.getTransactionReceipt(txHash);
// If block number of receipt is not null, compare it against finalized head
if (txReceipt) {
const txBlockNumber = txReceipt.blockNumber;
// As a safety check, get given block to check if transaction is included
const txBlock = await web3Provider.eth.getBlock(txBlockNumber);
console.log(`Current finalized block number is ${finalizedBlockNumber}`);
console.log(
`Your transaction in block ${txBlockNumber} is finalized? ${
finalizedBlockNumber >= txBlockNumber
}`
);
console.log(
`Your transaction is indeed in block ${txBlockNumber}? ${txBlock.transactions.includes(
txHash
)}`
);
} else {
console.log(
'Your transaction has not been included in the canonical chain'
);
}
};
main();
```
=== "Web3.py"
```py
from web3 import Web3
# Define the transaction hash to check finality
tx_hash = "INSERT_TX_HASH"
# Define the Web3 provider for Moonbeam
# This can be adapted for Moonriver or Moonbase Alpha
web3_provider = Web3(Web3.HTTPProvider("INSERT_RPC_API_ENDPOINT"))
if __name__ == "__main__":
# Get the latest finalized block
finalized_block_header = web3_provider.eth.get_block("finalized")
finalized_block_number = finalized_block_header.number
# Get the transaction receipt of the given transaction hash
tx_receipt = web3_provider.eth.get_transaction_receipt(tx_hash)
# If block number of receipt is not null, compare it against finalized head
if tx_receipt is not None:
tx_block_number = tx_receipt.blockNumber
# As a safety check, get given block to check if transaction is included
tx_block = web3_provider.eth.get_block(tx_block_number)
is_in_block = False
for tx in tx_block.transactions:
if tx_hash == web3_provider.to_hex(tx):
is_in_block = True
print(f"Current finalized block number is { str(finalized_block_number) }")
print(
f"Your transaction in block { str(tx_block_number) } is finalized? { str(finalized_block_number >= tx_block_number) }"
)
print(
f"Your transaction is indeed in block { str(tx_block_number) }? { is_in_block }"
)
else:
print("Your transaction has not been included in the canonical chain")
```
## Check Transaction Finality with Moonbeam RPC Endpoints {: #check-tx-finality-with-moonbeam-rpc-endpoints }
Moonbeam has added support for two custom RPC endpoints, `moon_isBlockFinalized` and `moon_isTxFinalized`, that can be used to check whether an on-chain event is finalized. These methods are a bit more straightforward, as you don't need to compare block numbers to ensure your transaction is finalized.
For more information, you can go to the [Finality RPC Endpoints](/builders/ethereum/json-rpc/moonbeam-custom-api/#rpc-methods){target=\_blank} section of the Moonbeam Custom API page.
You can modify the scripts from the Ethereum RPC section above to use `moon_isBlockFinalized` and `moon_isTxFinalized`. To do this, you can make custom calls to the Substrate JSON-RPC using the `send` method of both [Web3.js](https://web3js.readthedocs.io){target=\_blank} and [Ethers.js](https://docs.ethers.org/v6){target=\_blank}. Custom RPC requests are also possible using [Web3.py](https://web3py.readthedocs.io){target=\_blank} with the `make_request` method. You'll need to pass in the method name and the parameters to the custom request, which you can find on the [Moonbeam Custom API](/builders/ethereum/json-rpc/moonbeam-custom-api/){target=\_blank} page.
???+ code "moon_isBlockFinalized"
=== "Ethers.js"
```js
import { ethers } from 'ethers';
// Define the block hash to check finality
const blockHash = 'INSERT_BLOCK_HASH';
// Define the RPC of the provider for Moonbeam
// This can be adapted for Moonriver or Moonbase Alpha
const providerRPC = {
moonbeam: {
name: 'moonbeam',
rpc: 'INSERT_RPC_API_ENDPOINT',
chainId: 1284,
},
};
// Define the Web3 provider
const web3Provider = new ethers.JsonRpcProvider(providerRPC.moonbeam.rpc, {
chainId: providerRPC.moonbeam.chainId,
name: providerRPC.moonbeam.name,
});
// Define the function for the custom web3 request
const customWeb3Request = async (web3Provider, method, params) => {
try {
return await web3Provider.send(method, params);
} catch (error) {
throw new Error(error.body);
}
};
const main = async () => {
// Check if the block has been finalized
const isFinalized = await customWeb3Request(
web3Provider,
'moon_isBlockFinalized',
[blockHash]
);
console.log(`Block is finalized? ${isFinalized}`);
};
main();
```
=== "Web3.js"
```js
import { Web3 } from 'web3';
// Define the block hash to check finality
const blockHash = 'INSERT_BLOCK_HASH';
// Define the Web3 provider for Moonbeam
// This can be adapted for Moonriver or Moonbase Alpha
const web3Provider = new Web3('INSERT_RPC_API_ENDPOINT');
// Define the function for the custom Web3 request
const customWeb3Request = async (web3Provider, method, params) => {
try {
return await requestPromise(web3Provider, method, params);
} catch (error) {
throw new Error(error);
}
};
// In Web3.js you need to return a promise
const requestPromise = async (web3Provider, method, params) => {
return new Promise((resolve, reject) => {
web3Provider.send(
{
jsonrpc: '2.0',
id: 1,
method,
params,
},
(error, result) => {
if (error) {
reject(error.message);
} else {
if (result.error) {
reject(result.error.message);
}
resolve(result);
}
}
);
});
};
const main = async () => {
// Check if the block has been finalized
const isFinalized = await customWeb3Request(
web3Provider.currentProvider,
'moon_isBlockFinalized',
[blockHash]
);
console.log(JSON.stringify(isFinalized));
console.log(`Block is finalized? ${isFinalized.result}`);
};
main();
```
=== "Web3.py"
```py
from web3 import Web3
# Define the block hash to check finality
block_hash = 'INSERT_BLOCK_HASH'
# Set the RPC_address for Moonbeam
# This can also be adapted for Moonriver or Moonbase Alpha
RPC_address = 'INSERT_RPC_API_ENDPOINT'
# Define the Web3 provider
web3_provider = Web3(Web3.HTTPProvider(RPC_address))
# Asynchronous JSON-RPC API request
def custom_web3_request(method, params):
response = web3_provider.provider.make_request(method, params)
return response
if __name__ == "__main__":
# Check if the block has been finalized
is_finalized = custom_web3_request(
'moon_isBlockFinalized', [block_hash])
print(
f'Block is finalized? { is_finalized["result"] }')
```
??? code "moon_isTxFinalized"
=== "Ethers.js"
```js
import { ethers } from 'ethers';
// Define the transaction hash to check finality
const txHash = 'INSERT_TRANSACTION_HASH';
// Define the RPC of the provider for Moonbeam
// This can be adapted for Moonriver or Moonbase Alpha
const providerRPC = {
moonbeam: {
name: 'moonbeam',
rpc: 'INSERT_RPC_API_ENDPOINT',
chainId: 1284,
},
};
// Define the Web3 provider
const web3Provider = new ethers.JsonRpcProvider(providerRPC.moonbeam.rpc, {
chainId: providerRPC.moonbeam.chainId,
name: providerRPC.moonbeam.name,
});
// Define the function for the custom web3 request
const customWeb3Request = async (web3Provider, method, params) => {
try {
return await web3Provider.send(method, params);
} catch (error) {
throw new Error(error.body);
}
};
const main = async () => {
// Check if the transaction has been finalized
const isFinalized = await customWeb3Request(
web3Provider,
'moon_isTxFinalized',
[txHash]
);
console.log(`Transaction is finalized? ${isFinalized}`);
};
main();
```
=== "Web3.js"
```js
import Web3 from 'web3';
// Define the transaction hash to check finality
const txHash = 'INSERT_TRANSACTION_HASH';
// Define the Web3 provider for Moonbeam
// This can be adapted for Moonriver or Moonbase Alpha
const web3Provider = new Web3('INSERT_RPC_API_ENDPOINT');
// Define the function for the custom Web3 request
const customWeb3Request = async (web3Provider, method, params) => {
try {
return await requestPromise(web3Provider, method, params);
} catch (error) {
throw new Error(error);
}
};
// In Web3.js you need to return a promise
const requestPromise = async (web3Provider, method, params) => {
return new Promise((resolve, reject) => {
web3Provider.send(
{
jsonrpc: '2.0',
id: 1,
method,
params,
},
(error, result) => {
if (error) {
reject(error.message);
} else {
if (result.error) {
reject(result.error.message);
}
resolve(result);
}
}
);
});
};
const main = async () => {
// Check if the transaction has been finalized
const isFinalized = await customWeb3Request(
web3Provider.currentProvider,
'moon_isTxFinalized',
[txHash]
);
console.log(JSON.stringify(isFinalized));
console.log(`Transaction is finalized? ${isFinalized}`);
};
main();
```
=== "Web3.py"
```py
from web3 import Web3
# Define the transaction hash to check finality
tx_hash = 'INSERT_BLOCK_HASH'
# Set the RPC_address for Moonbeam
# This can also be adapted for Moonriver or Moonbase Alpha
RPC_address = 'INSERT_RPC_API_ENDPOINT'
# Define the Web3 provider
web3_provider = Web3(Web3.HTTPProvider(RPC_address))
# Asynchronous JSON-RPC API request
def custom_web3_request(method, params):
response = web3_provider.provider.make_request(method, params)
return response
if __name__ == "__main__":
# Check if the transaction has been finalized
is_finalized = custom_web3_request(
'moon_isTxFinalized', [tx_hash])
print(
f'Transaction is finalized? { is_finalized["result"] }')
```
## Check Transaction Finality with Substrate RPC Endpoints {: #check-tx-finality-with-substrate-rpc-endpoints }
Using the following three RPC requests from the Substrate JSON-RPC, you can fetch the current finalized block and compare it with the block number of the transaction you want to check finality for:
- `chain_getFinalizedHead` - the first request gets the block hash of the last finalized block
- `chain_getHeader` - the second request gets the block header for a given block hash
- `eth_getTransactionReceipt` - this retrieves the transaction receipt given the transaction hash
The [Polkadot.js API package](/builders/substrate/libraries/polkadot-js-api/){target=\_blank} and [Python Substrate Interface package](/builders/substrate/libraries/py-substrate-interface/){target=\_blank} provide developers with a way to interact with Substrate chains using JavaScript and Python.
You can find more information about Polkadot.js and the Substrate JSON-RPC in the [official Polkadot.js documentation site](https://polkadot.js.org/docs/substrate/rpc){target=\_blank}, and more about Python Substrate Interface in the [official PySubstrate documentation site](https://jamdottech.github.io/py-polkadot-sdk/){target=\_blank}.
=== "Polkadot.js"
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
import { types } from 'moonbeam-types-bundle';
// Define the transaction hash to check finality
const txHash = 'INSERT_TX_HASH';
// Define the provider for Moonbeam
// This can be adapted for Moonriver or Moonbase Alpha
const wsProvider = new WsProvider('INSERT_WSS_API_ENDPOINT');
const main = async () => {
// Create the provider using Moonbeam types
const polkadotApi = await ApiPromise.create({
provider: wsProvider,
typesBundle: types,
});
await polkadotApi.isReady;
// Get the latest finalized block of the Substrate chain
const finalizedHeadHash = (
await polkadotApi.rpc.chain.getFinalizedHead()
).toJSON();
// Get finalized block header to retrieve number
const finalizedBlockHeader = (
await polkadotApi.rpc.chain.getHeader(finalizedHeadHash)
).toJSON();
// Get the transaction receipt of the given tx hash
const txReceipt = (
await polkadotApi.rpc.eth.getTransactionReceipt(txHash)
).toJSON();
// You can not verify if the tx is in the block because polkadotApi.rpc.eth.getBlockByNumber
// does not return the list of tx hashes
// If block number of receipt is not null, compare it against finalized head
if (txReceipt) {
console.log(
`Current finalized block number is ${finalizedBlockHeader.number}`
);
console.log(
`Your transaction in block ${txReceipt.blockNumber} is finalized? ${
finalizedBlockHeader.number >= txReceipt.blockNumber
}`
);
} else {
console.log(
'Your transaction has not been included in the canonical chain'
);
}
polkadotApi.disconnect();
};
main();
```
=== "py-substrate-interface"
```py
from substrateinterface import SubstrateInterface
# Define the Ethereum transaction hash to check finality
tx_hash = "INSERT_TX_HASH"
# Point API provider to Moonbeam
# This can be adapted for Moonriver or Moonbase Alpha
moonbeam_API_provider = SubstrateInterface(
url="INSERT_WSS_API_ENDPOINT",
)
if __name__ == "__main__":
# Get the latest finalized block header of the chain
finalized_block_header = moonbeam_API_provider.get_block_header(finalized_only=True)
# Get the finalized block number from the block header
finalized_block_number = finalized_block_header["header"]["number"]
# Get the transaction receipt of the given transaction hash through a
# custom RPC request
tx_receipt = moonbeam_API_provider.rpc_request(
"eth_getTransactionReceipt", [tx_hash]
)
# Check if tx_receipt is null
if tx_receipt is None:
print("The transaction hash cannot be found in the canonical chain.")
else:
# Get the block number of the transaction
tx_block_number = int(tx_receipt["result"]["blockNumber"], 16)
# Get the transaction block through a custom RPC request
tx_block = moonbeam_API_provider.rpc_request(
"eth_getBlockByNumber", [tx_block_number, False]
)
print(f"Current finalized block number is { str(finalized_block_number) }")
print(
f"Your transaction in block { str(tx_block_number) } is finalized? { str(finalized_block_number >= tx_block_number) }"
)
print(
f'Your transaction is indeed in block { str(tx_block_number) }? { str(tx_hash in tx_block["result"]["transactions"]) }'
)
```
The information presented herein has been provided by third parties and is made available solely for general information purposes. Moonbeam does not endorse any project listed and described on the Moonbeam Doc Website (https://docs.moonbeam.network/). Moonbeam Foundation does not warrant the accuracy, completeness or usefulness of this information. Any reliance you place on such information is strictly at your own risk. Moonbeam Foundation disclaims all liability and responsibility arising from any reliance placed on this information by you or by anyone who may be informed of any of its contents. All statements and/or opinions expressed in these materials are solely the responsibility of the person or entity providing those materials and do not necessarily represent the opinion of Moonbeam Foundation. The information should not be construed as professional or financial advice of any kind. Advice from a suitably qualified professional should always be sought in relation to any particular matter or circumstance. The information herein may link to or integrate with other websites operated or content provided by third parties, and such other websites may link to this website. Moonbeam Foundation has no control over any such other websites or their content and will have no liability arising out of or related to such websites or their content. The existence of any such link does not constitute an endorsement of such websites, the content of the websites, or the operators of the websites. These links are being provided to you only as a convenience and you release and hold Moonbeam Foundation harmless from any and all liability arising from your use of this information or the information provided by any third-party website or service.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/core-concepts/security/
--- BEGIN CONTENT ---
---
title: Security Considerations
description: A description of the main differences that Ethereum developers need to understand in terms of security considerations when developing on Moonbeam.
categories: Basics
---
# Security Considerations
## Introduction {: #introduction }
When developing smart contracts on Moonbeam, there are some security considerations to be aware of that do not apply when developing on Ethereum. Moonbeam has several [precompiled contracts](/builders/ethereum/precompiles/){target=\_blank}, which are Solidity interfaces that enable developers to access Substrate-based functionality through the Ethereum API, but circumventing the EVM. Although the precompiled contracts are designed to improve the developer experience, there can be some unintended consequences that must be considered.
This guide will outline and provide examples of some security considerations to be cognizant of when developing on Moonbeam.
## Arbitrary Code Execution {: #arbitrary-code-execution }
Arbitrary code execution in Solidity is the ability to execute code and call functions of other contracts using an arbitrary number of arguments of any type.
A smart contract allows arbitrary execution of another contract when it allows a user to influence its own `call()` and pass in arbitrary call data and/or the `call()`s target. The [`call()` function](https://solidity-by-example.org/call){target=\_blank} is made available through the [address data type in Solidity](https://docs.soliditylang.org/en/latest/types.html#address){target=\_blank}. When the `call()` function is invoked, the target contract is called using the arbitrary call data.
Arbitrary code execution follows the pattern in the diagram below when **Contract A** allows a user to influence its call to **Contract B**.

As previously mentioned, one major concern of arbitrarily executing code on Moonbeam is that Moonbeam has precompile contracts that can be called, which can be used to get around some protections that are typically available on Ethereum. To safely use arbitrary code execution on Moonbeam, you should consider the following, which **only applies to contracts that allow arbitrary code execution**:
- Moonbeam [precompiled contracts](/builders/ethereum/precompiles/){target=\_blank} such as the Native ERC-20 precompile, XC-20 precompiles, and XCM-related precompiles allow users to manage and transfer assets without requiring access to the EVM. Instead, these actions are done using native Substrate code. So, if your contract holds native tokens or XC-20s and allows arbitrary code execution, these precompiles can be used to drain the balance of the contract, bypassing any security checks that are normally enforced by the EVM
- Setting the value attribute of the transaction object to a fixed amount when using the `call()` function (for example, `call{value: 0}(...)`) can be bypassed by calling the native asset precompile and specifying an amount to transfer in the encoded call data
- Allowing users that consume your contract to pass in arbitrary call data that will execute any function on the target contract, especially if the contract being targeted is a precompile, is **not** safe. To be safe, you can hard code the function selector for a safe function that you want to allow to be executed
- Blacklisting target contracts (including precompiles) in the function that executes arbitrary call data is **not** considered safe, as other precompiles might be added in the future. Providing whitelisted target contracts in the function that executes the arbitrary call data is considered safe, assuming that the contracts being called are not precompiles, or that in the case they are, the contract making the call does not hold the native token or any XC-20
In the following sections, you'll learn about each of these security considerations through examples.
### Precompiles Can Override a Set Value {: #setting-a-value }
On Ethereum, a smart contract that allows for arbitrary code execution could force the value of a call to be a specific amount (for example, `{value: 0}`), guaranteeing that only that amount of native currency would be sent with the transaction. Whereas on Moonbeam, the [native ERC-20 precompile contract](/builders/ethereum/precompiles/ux/erc20/){target=\_blank} enables you to interact with the native currency on Moonbeam as an ERC-20 through the Substrate API. As a result, you can transfer the Moonbeam native asset from a smart contract by setting the `value` of a call, as well as through the native ERC-20 precompile. If you set the `value` of an arbitrary call, it can be overridden by targeting the [native ERC-20 precompile contract](/builders/ethereum/precompiles/ux/erc20/){target=\_blank} and passing in call data to transfer the native asset. Since ERC-20s and XC-20s are not native assets, setting the value attribute doesn't provide any protection for these types of assets on Ethereum or Moonbeam.
For example, if you have a contract that allows arbitrary code execution and you pass it encoded call data that transfers the balance of a contract to another address, you could essentially drain the given contract of its balance.
To get the encoded call data, you can use any of the [ABI encoding functions outlined in the Solidity docs](https://docs.soliditylang.org/en/latest/units-and-global-variables.html#abi-encoding-and-decoding-functions){target=\_blank}, including `abi.encodeWithSelector` as seen in the following function:
```solidity
function getBytes(address _erc20Contract, address _arbitraryCallContract, address _to) public view returns (bytes memory) {
// Load ERC-20 interface of contract
IERC20 erc20 = IERC20(_erc20Contract);
// Get amount to transfer
uint256 amount = erc20.balanceOf(_arbitraryCallContract);
// Build the encoded call data
return abi.encodeWithSelector(IERC20.transfer.selector, _to, amount);
}
```
Once you have the encoded call data, you could make an arbitrary call to the [native ERC-20 precompile contract](/builders/ethereum/precompiles/ux/erc20/){target=\_blank}, set the value of the call to `0`, and pass in the call data in bytes:
```solidity
function makeArbitraryCall(address _target, bytes calldata _bytes) public {
// Value: 0 does not protect against native ERC-20 precompile calls or XCM precompiles
(bool success,) = _target.call{value: 0}(_bytes);
require(success);
}
```
The value of `0` will be overridden by the amount to be transferred as specified in the encoded call data, which in this example is the balance of the contract.
### Whitelisting Safe Function Selectors {: #whitelisting-function-selectors }
By whitelisting a specific function selector, you can control what functions can be executed and ensure only functions that are considered safe and do not call precompiles are allowed to be called.
To get the function selector to whitelist, you can [keccack256 hash](https://emn178.github.io/online-tools/keccak_256.html){target=\_blank} the signature of the function.
Once you have the whitelisted function selector, you can use inline assembly to get the function selector from the encoded call data and compare the two selectors using the [require function](https://docs.soliditylang.org/en/v0.8.17/control-structures.html#panic-via-assert-and-error-via-require){target=\_blank}. If the function selector from the encoded call data matches the whitelisted function selector, you can make the call. Otherwise, an exception will be thrown.
```solidity
function makeArbitraryCall(address _target, bytes calldata _bytes) public {
// Get the function selector from the encoded call data
bytes4 selector;
assembly {
selector := calldataload(_bytes.offset)
}
// Ensure the call data calls an approved and safe function
require(selector == INSERT_WHITELISTED_FUNCTION_SELECTOR);
// Arbitrary call
(bool success,) = _target.call(_bytes);
require(success);
}
```
### Whitelisting Safe Contracts {: #whitelisting-safe-contracts}
By whitelisting a specific target contract address in the function that can execute arbitrary call data, you can ensure that the call is considered safe, as the EVM will enforce that only whitelisted contracts can be called. This assumes that the contracts being called are not precompiles. If they are precompiles, you'll want to make sure that the contract making the call does not hold the native token or any XC-20.
Blacklisting contracts from arbitrary code execution is not considered safe, as other precompiles might be added in the future.
To whitelist a given contract, you can use the [require function](https://docs.soliditylang.org/en/v0.8.17/control-structures.html#panic-via-assert-and-error-via-require){target=\_blank}, which will compare the target contract address to the whitelisted contract address. If the addresses match, the call can be executed. Otherwise, an exception will be thrown.
```solidity
function makeArbitraryCall(address _target, bytes calldata _bytes) public {
// Ensure the contract address is safe
require(_target == INSERT_CONTRACT_ADDRESS);
// Arbitrary call
(bool success,) = _target.call(_bytes);
require(success);
}
```
## Precompiles Can Bypass Sender vs Origin Checks {: #bypass-sender-origin-checks }
The transaction origin, or `tx.origin`, is the address of the externally owned account (EOA) the transaction originated from. Whereas the `msg.sender` is the address that has initiated the current call. The `msg.sender` can be an EOA or a contract. The two can be different values if one contract calls another contract, as opposed to directly calling a contract from an EOA. In this case, the `msg.sender` will be the calling contract and the `tx.origin` will be the EOA that initially called the calling contract.
For example, if Alice calls a function in contract A that then calls a function in contract B, when looking at the call to contract B, the `tx.origin` is Alice and the `msg.sender` is contract A.
!!! note
As a [best practice](https://consensysdiligence.github.io/smart-contract-best-practices/development-recommendations/solidity-specific/tx-origin/){target=\_blank}, `tx.origin` should not be used for authorization. Instead, you should use `msg.sender`.
You can use the [require function](https://docs.soliditylang.org/en/v0.8.17/control-structures.html#panic-via-assert-and-error-via-require){target=\_blank} to compare the `tx.origin` and `msg.sender`. If they are the same address, you're ensuring that only EOAs can call the function. If the `msg.sender` is a contract address, an exception will be thrown.
```solidity
function transferFunds(address payable _target) payable public {
require(tx.origin == msg.sender);
_target.call{value: msg.value};
}
```
On Ethereum, you can use this check to ensure that a given contract function can only be called once by an EOA. This is because on Ethereum, EOAs can only interact with a contract once per transaction. However, **this is not the case** on Moonbeam, as EOAs can interact with a contract multiple times at once by using precompiled contracts, such as the [batch](/builders/ethereum/precompiles/ux/batch/){target=\_blank} and [call permit](/builders/ethereum/precompiles/ux/call-permit/){target=\_blank} precompiles.
With the batch precompile, users can perform multiple calls to a contract atomically. The caller of the batch function will be the `msg.sender` and `tx.origin`, enabling multiple contract interactions at once.
With the call permit precompile, if a user wants to interact with a contract multiple times in one transaction, they can do so by signing a permit for each contract interaction and dispatching all of the permits in a single function call. This will only bypass the `tx.origin == msg.sender` check if the dispatcher is the same account as the permit signer. Otherwise, the `msg.sender` will be the permit signer and the `tx.origin` will be the dispatcher, causing an exception to be thrown.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/core-concepts/transfers-api/
--- BEGIN CONTENT ---
---
title: Transfer & Monitor Balances on Moonbeam
description: A description of the main differences that developers need to understand in terms of the different balance transfers available on Moonbeam compared to Ethereum.
categories: Basics
---
# Balance Transfers on Moonbeam
## Introduction {: #introduction }
While Moonbeam strives to be compatible with Ethereum's Web3 API and EVM, there are some important Moonbeam differences that developers should know and understand in terms of balance transfers of the base network token (for example, GLMR and MOVR).
Token holders have two ways of initiating a balance transfer on Moonbeam. On the one hand, users can use the Ethereum API via apps like MetaMask, MathWallet, or any other tools that use the Ethereum JSON-RPC. On the other hand, users can use the Substrate API via the Polkadot.js Apps website or directly using the Substrate RPC.
Developers need to be aware that token holders can leverage both APIs to transfer the base-layer network token. Note that these comments do not apply to transfers of other assets, like ERC-20 based assets in the Moonriver or Moonbeam EVMs. Transfers of these assets are only done via the Ethereum APIs since these are smart contract interactions.
This guide will outline some of the main differences between both APIs for base-layer network token balance transfers and what to expect when using Moonbeam for the first time.
## Ethereum Transfers {: #ethereum-transfers }
A simple balance transfer using the Ethereum API relies on the `eth_sendRawTransaction` JSON-RPC. This can be done directly from one account to another or via a smart contract.
There are different strategies to listen for transfers or balance changes on Ethereum, which are not covered in this documentation. But they are all focused on different strategies using the Ethereum JSON-RPC.
## Moonbeam Transfers {: #moonbeam-transfers }
As stated before, Moonbeam enables token holders to execute base-layer network token transfers via both the Ethereum and Substrate API. There are multiple scenarios to trigger token transfers on Moonbeam. Consequently, to monitor all transfers, **you should use the Polkadot.js SDK** (Substrate API).
Before going over the different scenarios, there are two different elements associated with a block:
- **Extrinsic** — refers to state changes that originated outside of the system itself. The most common form of extrinsic is a transaction. They are ordered by execution
- **Events** — refers to logs generated from the extrinsic. There can be multiple events per extrinsic. They are ordered by execution
The different transfer scenarios are:
- **Substrate transfer** — it will create an extrinsic, either `balances.transferAllowDeath` or `balances.transferKeepAlive`. It will trigger **one** `balances.Transfer` event
- **Substrate feature** — some native Substrate features can create extrinsic that would send tokens to an address. For example, [Treasury](/learn/features/treasury/){target=\_blank} can create an extrinsic such as `treasury.proposeSend`, which will trigger **one or multiple** `balances.Transfer` events
- **Ethereum transfer** — it will create an `ethereum.transact` extrinsic with an empty input. It will trigger **one** `balances.Transfer` event
- **Ethereum transfers via smart contracts** — it will create an `ethereum.transact` extrinsic with some data as input. It will trigger **one or multiple** `balances.Transfer` events
All the scenarios described above will effectively transfer base-layer network tokens. The easiest way to monitor them all is to rely on the `balances.Transfer` event.
## Monitor Native Token Balance Transfers {: #monitor-transfers }
The following code samples will demonstrate how to listen to both types of native token transfers, sent via the Substrate or Ethereum API, using either the [Polkadot.js API library](https://polkadot.js.org/docs/api/start/){target=\_blank} or [Substrate API Sidecar](https://github.com/paritytech/substrate-api-sidecar){target=\_blank}. The following code snippets are for demo purposes only and should not be used without modification and further testing in a production environment.
### Using Polkadot.js API {: #using-polkadotjs-api }
The [Polkadot.js API package](https://polkadot.js.org/docs/api/start/){target=\_blank} provides developers a way to interact with Substrate chains using JavaScript.
The following code snippet uses [`subscribeFinalizedHeads`](https://polkadot.js.org/docs/substrate/rpc/#subscribefinalizedheads-header){target=\_blank} to subscribe to new finalized block headers, loops through extrinsics fetched from the block, and retrieves the events of each extrinsic. Then, it checks if any event corresponds to a `balances.Transfer` event. If so, it will extract the `from`, `to`, `amount`, and the `tx hash` of the transfer and display it on the console. Note that the `amount` is shown in the smallest unit (Wei). You can find all the available information about Polkadot.js and the Substrate JSON-RPC on their [official documentation site](https://polkadot.js.org/docs/substrate/rpc){target=\_blank}.
```ts
import { typesBundlePre900 } from 'moonbeam-types-bundle';
import { ApiPromise, WsProvider } from '@polkadot/api';
// This script will listen to all GLMR transfers (Substrate & Ethereum) and extract the tx hash
// It can be adapted for Moonriver or Moonbase Alpha
const main = async () => {
// Define the provider for Moonbeam
const wsProvider = new WsProvider('wss://wss.api.moonbeam.network');
// Create the provider using Moonbeam types
const polkadotApi = await ApiPromise.create({
provider: wsProvider,
typesBundle: typesBundlePre900 as any,
});
// Subscribe to finalized blocks
await polkadotApi.rpc.chain.subscribeFinalizedHeads(
async (lastFinalizedHeader) => {
const [{ block }, records] = await Promise.all([
polkadotApi.rpc.chain.getBlock(lastFinalizedHeader.hash),
polkadotApi.query.system.events.at(lastFinalizedHeader.hash),
]);
block.extrinsics.forEach((extrinsic, index) => {
const {
method: { args, method, section },
} = extrinsic;
const isEthereum = section == 'ethereum' && method == 'transact';
// Gets the transaction object
const tx = args[0] as any;
// Convert to the correct Ethereum Transaction format
const ethereumTx =
isEthereum &&
((tx.isLegacy && tx.asLegacy) ||
(tx.isEip1559 && tx.asEip1559) ||
(tx.isEip2930 && tx.asEip2930));
// Check if the transaction is a transfer
const isEthereumTransfer =
ethereumTx &&
ethereumTx.input.length === 0 &&
ethereumTx.action.isCall;
// Retrieve all events for this extrinsic
const events = records.filter(
({ phase }) =>
phase.isApplyExtrinsic && phase.asApplyExtrinsic.eq(index)
);
// This hash will only exist if the transaction was executed through Ethereum.
let ethereumHash = '';
if (isEthereum) {
// Search for Ethereum execution
events.forEach(({ event }) => {
if (event.section == 'ethereum' && event.method == 'Executed') {
ethereumHash = event.data[2].toString();
}
});
}
// Search if it is a transfer
events.forEach(({ event }) => {
if (event.section == 'balances' && event.method == 'Transfer') {
const from = event.data[0].toString();
const to = event.data[1].toString();
const balance = (event.data[2] as any).toBigInt();
const substrateHash = extrinsic.hash.toString();
console.log(
`Transfer from ${from} to ${to} of ${balance} (block #${lastFinalizedHeader.number})`
);
console.log(` - Triggered by extrinsic: ${substrateHash}`);
if (isEthereum) {
console.log(
` - Ethereum (isTransfer: ${isEthereumTransfer}) hash: ${ethereumHash}`
);
}
}
});
});
}
);
};
main();
```
In addition, you can find more sample code snippets related to more specific cases around balance transfers on this [GitHub page](https://gist.github.com/crystalin/b2ce44a208af60d62b5ecd1bad513bce){target=\_blank}.
### Using Substrate API Sidecar {: #using-substrate-api-sidecar }
Developers can also retrieve Moonbeam blocks and monitor transactions sent via both the Substrate and Ethereum APIs using [Substrate API Sidecar](https://github.com/paritytech/substrate-api-sidecar){target=\_blank}, a REST API service for interacting with blockchains built with the Substrate framework.
The following code snippet uses the Axios HTTP client to query the [Sidecar endpoint `/blocks/head`](https://paritytech.github.io/substrate-api-sidecar/dist){target=\_blank} for the latest finalized block and then decodes the block for the `from`, `to`, `value`, `tx hash`, and `transaction status` of native token transfers at both the EVM and Substrate API level.
```js
import axios from 'axios';
// This script will decode all native token transfers (Substrate & Ethereum) in a given Sidecar block, and extract the tx hash. It can be adapted for any Moonbeam network.
// Endpoint to retrieve the latest block
const endpoint = 'http://127.0.0.1:8080/blocks/head';
async function main() {
try {
// Retrieve the block from the Sidecar endpoint
const response = await axios.get(endpoint);
// Retrieve the block height of the current block
console.log('Block Height: ' + response.data.number);
// Iterate through all extrinsics in the block
response.data.extrinsics.forEach((extrinsic) => {
// Retrieve Ethereum Transfers
if (
extrinsic.method.pallet === 'ethereum' &&
extrinsic.method.method === 'transact'
) {
// Get the value for any of the three EIP transaction standards supported
const value =
(extrinsic.args.transaction.legacy &&
extrinsic.args.transaction.legacy.value) ||
(extrinsic.args.transaction.eip1559 &&
extrinsic.args.transaction.eip1559.value) ||
(extrinsic.args.transaction.eip2930 &&
extrinsic.args.transaction.eip2930.value);
// Iterate through the events to get transaction details
extrinsic.events.forEach((event) => {
if (
event.method.pallet === 'ethereum' &&
event.method.method === 'Executed'
) {
console.log('From: ' + event.data[0]);
console.log('To: ' + event.data[1]);
console.log('Tx Hash: ' + event.data[2]);
console.log('Value: ' + value);
// Check the execution status
if (event.data[3].succeed) {
console.log('Status: Success');
} else {
console.log('Status: Failed');
}
}
});
}
// Retrieve Substrate Transfers
if (
extrinsic.method.pallet === 'balances' &&
(extrinsic.method.method === 'transferKeepAlive' ||
extrinsic.method.method === 'transferAllowDeath')
) {
// Iterate through the events to get transaction details
extrinsic.events.forEach((event) => {
if (
event.method.pallet === 'balances' &&
event.method.method === 'Transfer'
) {
console.log('From: ' + event.data[0]);
console.log('To: ' + event.data[1]);
console.log('Tx Hash: ' + extrinsic.hash);
console.log('Value: ' + event.data[2]);
// Check the execution status
if (extrinsic.success) {
console.log('Status: Success');
} else {
console.log('Status: Failed');
}
}
});
}
});
} catch (err) {
console.log(err);
}
}
main();
```
You can reference the [Substrate API Sidecar page](/builders/substrate/libraries/sidecar/) for information on installing and running your own Sidecar service instance, as well as more details on how to decode Sidecar blocks for Moonbeam transactions.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/core-concepts/tx-fees/
--- BEGIN CONTENT ---
---
title: Calculating Transaction Fees
description: Learn about the transaction fee model used in Moonbeam and the differences compared to Ethereum that developers should be aware of.
categories: Basics
---
# Calculating Transaction Fees on Moonbeam
## Introduction {: #introduction }
Similar to [the Ethereum and Substrate APIs for sending transfers](/learn/core-concepts/transfers-api/){target=\_blank} on Moonbeam, the Substrate and EVM layers on Moonbeam also have distinct transaction fee models that developers should be aware of when they need to calculate and keep track of transaction fees for their transactions.
For starters, Ethereum transactions consume gas units based on their computational complexity and data storage requirements. On the other hand, Substrate transactions use the concept of "weight" to determine fees. In this guide, you'll learn how to calculate the transaction fees for both Substrate and Ethereum transactions. In terms of Ethereum transactions, you'll also learn about the key differences between how transaction fees are calculated on Moonbeam and Ethereum.
### Key Differences with Ethereum {: #key-differences-with-ethereum}
There are some key differences between the transaction fee model on Moonbeam and the one on Ethereum that developers should be mindful of when developing on Moonbeam:
- The [dynamic fee mechanism](https://forum.moonbeam.network/t/proposal-status-idea-dynamic-fee-mechanism-for-moonbeam-and-moonriver/241){target=\_blank} resembles that of [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559){target=\_blank} but the implementation is different
- The amount of gas used in Moonbeam's transaction fee model is mapped from the transaction's Substrate extrinsic `refTime` component of the transaction weight via a fixed factor of `{{ networks.moonbase.tx_weight_to_gas_ratio }}` and `proofSize` component of the transaction weight via a fixed factor of `{{ xcm.generic_weights.proof_size.weight_per_gas }}`. The transaction weight vector is then multiplied with the unit gas price to calculate the transaction fee. This fee model means it can potentially be significantly cheaper to send transactions such as basic balance transfers via the Ethereum API than the Substrate API.
- The EVM is designed to solely have capacity for gas and Moonbeam requires additional metrics outside of gas. In particular, Moonbeam needs the ability to record proof size, which is the amount of storage required on Moonbeam for a relay chain validator to verify a state transition. When the capacity limit for proof size has been reached for the current block, which is 25% of the block limit, an "Out of Gas" error will be thrown. This can happen even if there is remaining *legacy* gas in the gasometer. This additional metric also impacts refunds. Refunds are based on the more consumed resource after the execution. In other words, if more proof size has been consumed proportionally than legacy gas, the refund will be calculated using proof size
- Moonbeam has implemented a new mechanism defined in [MBIP-5](https://github.com/moonbeam-foundation/moonbeam/blob/master/MBIPS/MBIP-5.md){target=\_blank} that limits block storage and increases gas usage for transactions that result in an increase in storage
## Overview of MBIP-5 {: #overview-of-mbip-5 }
MBIP-5 introduced changes to Moonbeam's fee mechanism that account for storage growth on the network, which deviates from the way Ethereum handles fees. By raising the gas needed to execute transactions that increase chain state and by establishing a block storage limit, it controls storage growth.
This impacts contract deployments that add to the chain state, transactions that create new storage entries, and precompiled contract calls that result in the creation of new accounts.
The block storage limit prevents transactions in a single block from collectively increasing the storage state by more than the limit. The limit for each network is as follows:
=== "Moonbeam"
```text
{{ networks.moonbeam.mbip_5.block_storage_limit }}KB
```
=== "Moonriver"
```text
{{ networks.moonriver.mbip_5.block_storage_limit }}KB
```
=== "Moonbase Alpha"
```text
{{ networks.moonbase.mbip_5.block_storage_limit }}KB
```
To determine the amount of gas for storage in bytes, there is a ratio that is defined as:
```text
Ratio = Block Gas Limit / (Block Storage Limit * 1024 Bytes)
```
The block gas limit for each network is as follows:
=== "Moonbeam"
```text
{{ networks.moonbeam.gas_block }}
```
=== "Moonriver"
```text
{{ networks.moonriver.gas_block }}
```
=== "Moonbase Alpha"
```text
{{ networks.moonbase.gas_block }}
```
Knowing the block gas and storage limits, the ratio of gas to storage is computed as follows:
=== "Moonbeam"
```text
Ratio = {{ networks.moonbeam.gas_block_numbers_only }} / ({{ networks.moonbeam.mbip_5.block_storage_limit }} * 1024)
Ratio = {{ networks.moonbeam.mbip_5.gas_storage_ratio }}
```
=== "Moonriver"
```text
Ratio = {{ networks.moonriver.gas_block_numbers_only }} / ({{ networks.moonriver.mbip_5.block_storage_limit }} * 1024)
Ratio = {{ networks.moonriver.mbip_5.gas_storage_ratio }}
```
=== "Moonbase Alpha"
```text
Ratio = {{ networks.moonbase.gas_block_numbers_only }} / ({{ networks.moonbase.mbip_5.block_storage_limit }} * 1024)
Ratio = {{ networks.moonbase.mbip_5.gas_storage_ratio }}
```
Then, you can take the storage growth in bytes for a given transaction and multiply it by the gas-to-storage growth ratio to determine how many units of gas to add to the transaction. For example, if you execute a transaction that increases the storage by {{ networks.moonbase.mbip_5.example_storage }} bytes, the following calculation is used to determine the units of gas to add:
=== "Moonbeam"
```text
Additional Gas = {{ networks.moonbeam.mbip_5.example_storage }} * {{ networks.moonbeam.mbip_5.gas_storage_ratio }}
Additional Gas = {{ networks.moonbeam.mbip_5.example_addtl_gas }}
```
=== "Moonriver"
```text
Additional Gas = {{ networks.moonriver.mbip_5.example_storage }} * {{ networks.moonriver.mbip_5.gas_storage_ratio }}
Additional Gas = {{ networks.moonriver.mbip_5.example_addtl_gas }}
```
=== "Moonbase Alpha"
```text
Additional Gas = {{ networks.moonbase.mbip_5.example_storage }} * {{ networks.moonbase.mbip_5.gas_storage_ratio }}
Additional Gas = {{ networks.moonbase.mbip_5.example_addtl_gas }}
```
To see how this MBIP differentiates Moonbeam from Ethereum firsthand, you can estimate the gas for two different contract interactions on both networks: one that modifies an item in the chain state and one that doesn't. For example, you can use a greeting contract that allows you to store a name and then use the name to say "Hello".
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SayHello {
mapping(address => string) public addressToName;
constructor(string memory _name) {
addressToName[msg.sender] = _name;
}
// Store a name associated to the address of the sender
function setName(string memory _name) public {
addressToName[msg.sender] = _name;
}
// Use the name in storage associated to the sender
function sayHello() external view returns (string memory) {
return string(abi.encodePacked("Hello ", addressToName[msg.sender]));
}
}
```
You can deploy this contract on both Moonriver and Ethereum, or on Moonbeam's TestNet, Moonbase Alpha, and Ethereum's TestNet, Sepolia. The above contract has already been deployed to Moonbase Alpha and Sepolia. You can feel free to access these contracts at the following addresses:
=== "Moonbase Alpha"
```text
0xDFF8E772A9B212dc4FbA19fa650B440C5c7fd7fd
```
=== "Sepolia"
```text
0x8D0C059d191011E90b963156569A8299d7fE777d
```
Next, you can use the `eth_estimateGas` method to check the gas estimate for calling the `setName` and `sayHello` functions on each network. To do so, you'll need the bytecode for each transaction, which includes the function selector, and for the `setName` function, the name to be set. This example bytecode sets the name to "Chloe":
=== "Set Name"
```text
0xc47f00270000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000543686c6f65000000000000000000000000000000000000000000000000000000
```
=== "Say Hello"
```text
0xef5fb05b
```
Now, you can use the following curl commands on Moonbase Alpha to return the gas estimate:
=== "Set Name"
```sh
curl {{ networks.moonbase.rpc_url }} -H "Content-Type:application/json;charset=utf-8" -d \
'{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_estimateGas",
"params":[{
"to": "0xDFF8E772A9B212dc4FbA19fa650B440C5c7fd7fd",
"data": "0xc47f00270000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000543686c6f65000000000000000000000000000000000000000000000000000000"
}]
}'
```
=== "Say Hello"
```sh
curl {{ networks.moonbase.rpc_url }} -H "Content-Type:application/json;charset=utf-8" -d \
'{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_estimateGas",
"params":[{
"to": "0xDFF8E772A9B212dc4FbA19fa650B440C5c7fd7fd",
"data": "0xef5fb05b"
}]
}'
```
Then on Sepolia, you can use the same bytecode for the `data` and modify the RPC URL and contract address to target the contract deployed to Sepolia:
=== "Set Name"
```sh
curl https://sepolia.publicgoods.network -H "Content-Type:application/json;charset=utf-8" -d \
'{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_estimateGas",
"params":[{
"to": "0x8D0C059d191011E90b963156569A8299d7fE777d",
"data": "0xc47f00270000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000543686c6f65000000000000000000000000000000000000000000000000000000"
}]
}'
```
=== "Say Hello"
```sh
curl https://sepolia.publicgoods.network -H "Content-Type:application/json;charset=utf-8" -d \
'{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_estimateGas",
"params":[{
"to": "0x8D0C059d191011E90b963156569A8299d7fE777d",
"data": "0xef5fb05b"
}]
}'
```
At the time of writing, the gas estimates for both networks are as follows:
=== "Moonbase Alpha"
| Method | Gas Estimate |
|:----------:|:------------:|
| `setName` | 45977 |
| `sayHello` | 25938 |
=== "Sepolia"
| Method | Gas Estimate |
|:----------:|:------------:|
| `setName` | 21520 |
| `sayHello` | 21064 |
You'll see that on Sepolia, the gas estimates for both calls are very similar, whereas on Moonbase Alpha, there is a noticeable difference between the calls and that the `setName` call, which modifies the storage, uses more gas than the `sayHello` call.
## Ethereum API Transaction Fees {: #ethereum-api-transaction-fees }
To calculate the fee incurred on a Moonbeam transaction sent via the Ethereum API, the following formula can be used:
=== "EIP-1559"
```text
GasPrice = BaseFee + MaxPriorityFeePerGas < MaxFeePerGas ?
BaseFee + MaxPriorityFeePerGas :
MaxFeePerGas;
Transaction Fee = (GasPrice * TransactionWeight) / {{ networks.moonbase.tx_weight_to_gas_ratio }}
```
=== "Legacy"
```text
Transaction Fee = (GasPrice * TransactionWeight) / {{ networks.moonbase.tx_weight_to_gas_ratio }}
```
=== "EIP-2930"
```text
Transaction Fee = (GasPrice * TransactionWeight) / {{ networks.moonbase.tx_weight_to_gas_ratio }}
```
!!! note
EIP-1559 transaction fees on Moonbeam are calculated using the previous block's base fee.
The following sections describe in more detail each of the components needed to calculate the transaction fee.
### Base Fee {: #base-fee}
The `BaseFee` is the minimum amount charged to send a transaction and is a value set by the network itself. It was introduced in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559){target=\_blank}. Moonbeam has its own [dynamic fee mechanism](https://forum.moonbeam.network/t/proposal-status-idea-dynamic-fee-mechanism-for-moonbeam-and-moonriver/241){target=\_blank} for calculating the base fee, which is adjusted based on block congestion. As of runtime 2300, the dynamic fee mechanism has been rolled out to all of the Moonbeam-based networks.
The minimum gas price for each network is as follows:
=== "Moonbeam"
| Variable | Value |
|:-----------------:|:------------------------------------------:|
| Minimum Gas Price | {{ networks.moonbeam.min_gas_price }} Gwei |
=== "Moonriver"
| Variable | Value |
|:-----------------:|:------------------------------------------:|
| Minimum Gas Price | {{ networks.moonriver.min_gas_price }} Gwei |
=== "Moonbase Alpha"
| Variable | Value |
|:-----------------:|:------------------------------------------:|
| Minimum Gas Price | {{ networks.moonbase.min_gas_price }} Gwei |
To calculate the dynamic base fee, the following calculation is used:
=== "Moonbeam"
```text
BaseFee = NextFeeMultiplier * 31250000000 / 10^18
```
=== "Moonriver"
```text
BaseFee = NextFeeMultiplier * 312500000 / 10^18
```
=== "Moonbase Alpha"
```text
BaseFee = NextFeeMultiplier * 31250000 / 10^18
```
The value of `NextFeeMultiplier` can be retrieved from the Substrate Sidecar API, via the following endpoint:
```text
GET /pallets/transaction-payment/storage/nextFeeMultiplier?at={blockId}
```
The pallets endpoints for Sidecar returns data relevant to a pallet, such as data in a pallet's storage. You can read more about the pallets endpoint in the [official Sidecar documentation](https://paritytech.github.io/substrate-api-sidecar/dist/#operations-tag-pallets){target=\_blank}. The data at hand that's required from storage is the `nextFeeMultiplier`, which can be found in the `transaction-payment` pallet. The stored `nextFeeMultiplier` value can be read directly from the Sidecar storage schema. Read as a JSON object, the relevant nesting structure is as follows:
```text
RESPONSE JSON Storage Object:
|--at
|--hash
|--height
|--pallet
|--palletIndex
|--storageItem
|--keys
|--value
```
The relevant data will be stored in the `value` key of the JSON object. This value is a fixed point data type, hence the real value is found by dividing the `value` by `10^18`. This is why [the calculation of `BaseFee`](#ethereum-api-transaction-fees) includes such an operation.
### GasPrice, MaxFeePerGas, and MaxPriorityFeePerGas {: #gasprice-maxfeepergas-maxpriorityfeepergas }
The `GasPrice` is used to specify the gas price of legacy transactions prior to [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559){target=\_blank}. The `MaxFeePerGas` and `MaxPriorityFeePerGas` were both introduced in EIP-1559 alongside the `BaseFee`. The `MaxFeePerGas` defines the maximum fee permitted to be paid per unit of gas and is the sum of the `BaseFee` and the `MaxPriorityFeePerGas`. The `MaxPriorityFeePerGas` is the maximum priority fee configured by the sender of a transaction that is used to incentivize the prioritization of a transaction in a block.
Although Moonbeam is Ethereum-compatible, it is also a Substrate-based chain at its core, and priorities work differently in Substrate than in Ethereum. In Substrate, transactions are not prioritized by gas price. To address this, Moonbeam uses a modified prioritization system that reprioritizes Substrate transactions using an Ethereum-first solution. A Substrate transaction still goes through the validity process, where it is assigned transaction tags, longevity, and a priority. The original priority is then overwritten with a new priority based on the transaction's fee per gas, which is derived from the transaction's tip and weight. If the transaction is an Ethereum transaction, the priority is set according to the priority fee.
It's important to note that priority is not the sole component responsible for determining the order of transactions in a block. Other components, such as the longevity of a transaction, also play a role in the sorting process.
The values of `GasPrice`, `MaxFeePerGas` and `MaxPriorityFeePerGas` for the applicable transaction types can be read from the block JSON object according to the structure described in [the Sidecar API page](/builders/substrate/libraries/sidecar/#evm-fields-mapping-in-block-json-object){target=\_blank}.
The data for an Ethereum transaction in a particular block can be extracted from the following block endpoint:
```text
GET /blocks/{blockId}
```
The paths to the relevant values have also been truncated and reproduced below:
=== "EIP1559"
| EVM Field | Block JSON Field |
|:--------------------:|:----------------------------------------------------------------------------:|
| MaxFeePerGas | `extrinsics[extrinsic_number].args.transaction.eip1559.maxFeePerGas` |
| MaxPriorityFeePerGas | `extrinsics[extrinsic_number].args.transaction.eip1559.maxPriorityFeePerGas` |
=== "Legacy"
| EVM Field | Block JSON Field |
|:---------:|:---------------------------------------------------------------:|
| GasPrice | `extrinsics[extrinsic_number].args.transaction.legacy.gasPrice` |
=== "EIP2930"
| EVM Field | Block JSON Field |
|:---------:|:----------------------------------------------------------------:|
| GasPrice | `extrinsics[extrinsic_number].args.transaction.eip2930.gasPrice` |
### Transaction Weight {: #transaction-weight}
`TransactionWeight` is a Substrate mechanism used to measure the execution time a given transaction takes to be executed within a block. A transaction's weight is a vector of two components: `refTime` and `proofSize`. `refTime` refers to the amount of computational time that can be used for execution. `proofSize` refers to the size of the PoV (Proof of Validity) of the Moonbeam block that gets submitted to the Polkadot Relay Chain for validation. Since both `refTime` and `proofSize` are integral components of determining a weight, it is impossible to obtain an accurate weight value with just one of these values.
For all transactions types, `TransactionWeight` can be retrieved under the event of the relevant extrinsic where the `method` field is set to:
```text
pallet: "system", method: "ExtrinsicSuccess"
```
And then `TransactionWeight` is mapped to the following two fields of the block JSON object. `proofSize` is mapped as follows:
```text
extrinsics[extrinsic_number].events[event_number].data[0].weight.proof_size
```
And `refTime` is mapped as follows:
```text
extrinsics[extrinsic_number].events[event_number].data[0].weight.ref_time
```
### Fee History Endpoint {: #eth-feehistory-endpoint }
Moonbeam networks implement the [`eth_feeHistory`](https://www.alchemy.com/docs/node/ethereum/ethereum-api-endpoints/eth-fee-history){target_blank} JSON-RPC endpoint as a part of the support for EIP-1559.
`eth_feeHistory` returns a collection of historical gas information from which you can reference and calculate what to set for the `MaxFeePerGas` and `MaxPriorityFeePerGas` fields when submitting EIP-1559 transactions.
The following curl example will return the gas information of the last 10 blocks starting from the latest block on the respective Moonbeam network using `eth_feeHistory`:
=== "Moonbeam"
```sh
curl --location \
--request POST '{{ networks.moonbeam.rpc_url }}' \
--header 'Content-Type: application/json' \
--data-raw '{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_feeHistory",
"params": ["0xa", "latest"]
}'
```
=== "Moonriver"
```sh
curl --location \
--request POST '{{ networks.moonriver.rpc_url }}' \
--header 'Content-Type: application/json' \
--data-raw '{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_feeHistory",
"params": ["0xa", "latest"]
}'
```
=== "Moonbase Alpha"
```sh
curl --location \
--request POST '{{ networks.moonbase.rpc_url }}' \
--header 'Content-Type: application/json' \
--data-raw '{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_feeHistory",
"params": ["0xa", "latest"]
}'
```
=== "Moonbeam Dev Node"
```sh
curl --location \
--request POST '{{ networks.development.rpc_url }}' \
--header 'Content-Type: application/json' \
--data-raw '{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_feeHistory",
"params": ["0xa", "latest"]
}'
```
### Sample Code for Calculating Transaction Fees {: #sample-code }
The following code snippet uses the [Axios HTTP client](https://axios-http.com){target=\_blank} to query the [Sidecar endpoint `/blocks/head`](https://paritytech.github.io/substrate-api-sidecar/dist/#operations-tag-blocks){target=\_blank} for the latest finalized block. It then calculates the transaction fees of all transactions in the block according to the transaction type (for Ethereum API: legacy, EIP-1559 or EIP-2930 standards, and for Substrate API), as well as calculating the total transaction fees in the block.
!!! note
EIP-1559 transaction fees on Moonbeam are calculated using the previous block's base fee.
The following code sample is for demo purposes only and should not be used without modification and further testing in a production environment.
You can use the following snippet for any Moonbeam-based network, but you'll need to modify the `baseFee` accordingly. You can refer back to the [Base Fee](#base-fee) section to get the calculation for each network.
```js
import axios from 'axios';
// This script calculates the transaction fees of all transactions in a block
// according to the transaction type (for Ethereum API: legacy, EIP-1559 or
// EIP-2930 standards, and Substrate API) using the dynamic fee mechanism.
// It also calculates the total fees in the block
// Endpoint to retrieve the latest block
const endpointBlock = 'http://127.0.0.1:8080/blocks/head';
// Endpoint to retrieve the latest nextFeeMultiplier
const endpointPallet =
'http://127.0.0.1:8080/pallets/transaction-payment/storage/nextFeeMultiplier?at=';
// Endpoint to retrieve the node client's information
const endpointNodeVersion = 'http://127.0.0.1:8080/node/version';
// Define the minimum base fee for each network
const baseFee = {
moonbeam: 31250000000n,
moonriver: 312500000n,
moonbase: 31250000n,
};
async function main() {
try {
// Create a variable to sum the transaction fees in the whole block
let totalFees = 0n;
// Find which Moonbeam network the Sidecar is pointing to
const responseClient = await axios.get(endpointNodeVersion);
const network = responseClient.data.clientImplName;
// Retrieve the block from the Sidecar endpoint
const responseBlock = await axios.get(endpointBlock);
// Retrieve the block height of the current block
console.log('Block Height: ' + responseBlock.data.number);
// Use the previous block's base fee to match the on-chain data
// Find the block's nextFeeMultiplier
const prevBlock = Number(responseBlock.data.number) - 1;
const responsePallet = await axios.get(endpointPallet + prevBlock);
// Iterate through all extrinsics in the block
responseBlock.data.extrinsics.forEach((extrinsic) => {
// Create an object to store transaction information
let transactionData = new Object();
// Set the network field
transactionData['network'] = network;
// Filter for Ethereum Transfers
if (
extrinsic.method.pallet === 'ethereum' &&
extrinsic.method.method === 'transact'
) {
// Iterate through the events to get non type specific parameters
extrinsic.events.forEach((event) => {
if (
event.method.pallet === 'ethereum' &&
event.method.method === 'Executed'
) {
// Get Transaction Hash
transactionData['hash'] = event.data[2];
}
if (
event.method.pallet === 'system' &&
event.method.method === 'ExtrinsicSuccess'
) {
// Add correction weight if needed to Transaction Weight!
transactionData['weight'] = BigInt(event.data[0].weight.refTime);
}
});
// Get the transaction type and type specific parameters and compute the
// transaction fee
if (extrinsic.args.transaction.legacy) {
transactionData['txType'] = 'legacy';
transactionData['gasPrice'] = BigInt(
extrinsic.args.transaction.legacy.gasPrice
);
transactionData['txFee'] =
(transactionData['gasPrice'] * transactionData['weight']) / 25000n;
} else if (extrinsic.args.transaction.eip1559) {
transactionData['txType'] = 'eip1599';
transactionData['maxFeePerGas'] = BigInt(
extrinsic.args.transaction.eip1559.maxFeePerGas
);
transactionData['maxPriorityFeePerGas'] = BigInt(
extrinsic.args.transaction.eip1559.maxPriorityFeePerGas
);
// Update based on the network you're getting tx fees for
transactionData['baseFee'] =
(BigInt(responsePallet.data.value) * baseFee.moonbeam) /
BigInt('1000000000000000000');
// Gas price dependes on the MaxFeePerGas and MaxPriorityFeePerGas set
transactionData['gasPrice'] =
transactionData['baseFee'] +
transactionData['maxPriorityFeePerGas'] <
transactionData['maxFeePerGas']
? transactionData['baseFee'] +
transactionData['maxPriorityFeePerGas']
: transactionData['maxFeePerGas'];
transactionData['txFee'] =
(transactionData['gasPrice'] * transactionData['weight']) / 25000n;
} else if (extrinsic.args.transaction.eip2930) {
transactionData['txType'] = 'eip2930';
transactionData['gasPrice'] = BigInt(
extrinsic.args.transaction.eip2930.gasPrice
);
transactionData['txFee'] =
(transactionData['gasPrice'] * transactionData['weight']) / 25000n;
}
// Increment totalFees
totalFees += transactionData['txFee'];
// Display the tx information to console
console.log(transactionData);
}
// Filter for Substrate transactions, check if the extrinsic has a
// 'TransactionFeePaid' event
else {
extrinsic.events.forEach((event) => {
if (
event.method.pallet === 'transactionPayment' &&
event.method.method === 'TransactionFeePaid'
) {
transactionData['txType'] = 'substrate';
transactionData['txFee'] = event.data[1];
transactionData['tip'] = event.data[1];
}
if (
event.method.pallet === 'system' &&
event.method.method === 'ExtrinsicSuccess'
) {
transactionData['weight'] = event.data[0].weight.refTime;
}
});
}
});
// Output the total amount of fees in the block
console.log('Total fees in block: ' + totalFees);
} catch (err) {
console.log(err);
}
}
main();
```
## Substrate API Transaction Fees {: #substrate-api-transaction-fees }
This section of the guide assumes you are interacting with Moonbeam blocks via [the Substrate API Sidecar](/builders/substrate/libraries/sidecar/){target=\_blank} service. There are other ways of interacting with Moonbeam blocks, such as using [the Polkadot.js API library](/builders/substrate/libraries/polkadot-js-api/){target=\_blank}. The logic is identical once the blocks are retrieved.
You can reference the [Substrate API Sidecar page](/builders/substrate/libraries/sidecar/){target=\_blank} for information on installing and running your own Sidecar service instance, as well as more details on how to decode Sidecar blocks for Moonbeam transactions.
**Note that the information in this section assumes you are running version {{ networks.moonbase.substrate_api_sidecar.stable_version }} of the Substrate Sidecar REST API.**
All the information around fee data for transactions sent via the Substrate API can be extracted from the following block endpoint:
```text
GET /blocks/{blockId}
```
The block endpoints will return data relevant to one or more blocks. You can read more about the block endpoints on the [official Sidecar documentation](https://paritytech.github.io/substrate-api-sidecar/dist/#operations-tag-blocks){target=\_blank}. Read as a JSON object, the relevant nesting structure is as follows:
```text
RESPONSE JSON Block Object:
...
|--number
|--extrinsics
|--{extrinsic_number}
|--method
|--signature
|--nonce
|--args
|--tip
|--hash
|--info
|--era
|--events
|--{event_number}
|--method
|--pallet: "transactionPayment"
|--method: "TransactionFeePaid"
|--data
|--0
|--1
|--2
...
```
The object mappings are summarized as follows:
| Tx Information | Block JSON Field |
|:------------------:|:-----------------------------------------------------------:|
| Fee paying account | `extrinsics[extrinsic_number].events[event_number].data[0]` |
| Total fees paid | `extrinsics[extrinsic_number].events[event_number].data[1]` |
| Tip | `extrinsics[extrinsic_number].events[event_number].data[2]` |
The transaction fee related information can be retrieved under the event of the relevant extrinsic where the `method` field is set to:
```text
pallet: "transactionPayment", method: "TransactionFeePaid"
```
And then the total transaction fee paid for this extrinsic is mapped to the following field of the block JSON object:
```text
extrinsics[extrinsic_number].events[event_number].data[1]
```
The information presented herein has been provided by third parties and is made available solely for general information purposes. Moonbeam does not endorse any project listed and described on the Moonbeam Doc Website (https://docs.moonbeam.network/). Moonbeam Foundation does not warrant the accuracy, completeness or usefulness of this information. Any reliance you place on such information is strictly at your own risk. Moonbeam Foundation disclaims all liability and responsibility arising from any reliance placed on this information by you or by anyone who may be informed of any of its contents. All statements and/or opinions expressed in these materials are solely the responsibility of the person or entity providing those materials and do not necessarily represent the opinion of Moonbeam Foundation. The information should not be construed as professional or financial advice of any kind. Advice from a suitably qualified professional should always be sought in relation to any particular matter or circumstance. The information herein may link to or integrate with other websites operated or content provided by third parties, and such other websites may link to this website. Moonbeam Foundation has no control over any such other websites or their content and will have no liability arising out of or related to such websites or their content. The existence of any such link does not constitute an endorsement of such websites, the content of the websites, or the operators of the websites. These links are being provided to you only as a convenience and you release and hold Moonbeam Foundation harmless from any and all liability arising from your use of this information or the information provided by any third-party website or service.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/core-concepts/unified-accounts/
--- BEGIN CONTENT ---
---
title: Unified Accounts
description: Moonbeam replaced the default Substrate account system with native support for the Ethereum-based H160 accounts and ECDSA keys. Find out more information!
categories: Basics
---
# Unified Accounts
## Introduction {: #introduction }
As Moonbeam is designed to be an Ethereum-compatible parachain on Polkadot, the underlying account system replaces the default Substrate-style accounts and keys with Ethereum-style accounts and keys. As a result, you can interact with your Moonbeam account using [MetaMask](/tokens/connect/metamask/){target=\_blank} and Ethereum tools you may already be familiar with, such as [Remix](/builders/ethereum/dev-env/remix/){target=\_blank} and [Hardhat](/builders/ethereum/dev-env/hardhat/){target=\_blank}.
You can also interact with your Moonbeam account using Polkadot.js Apps as it natively supports H160 addresses and ECDSA keys. For more information on this integration, you can check out the [Interacting with Moonbeam Using Polkadot.js Apps](/tokens/connect/polkadotjs/){target=\_blank} guide.
## Substrate EVM Compatible Blockchain {: #substrate-evm-compatible-blockchain }
Any parachain in the Polkadot ecosystem can offer a full EVM implementation, which provides the possibility of executing Solidity-based smart contracts with minimal to no changes. Substrate makes this integration possible - just plug the [EVM pallet](https://docs.rs/pallet-evm/2.0.1/pallet_evm){target=\_blank} into your runtime for EVM support, and the [Ethereum Pallet with Frontier](https://github.com/polkadot-evm/frontier){target=\_blank} to have Ethereum RPC compatibility. The availability of these open-source modules that Moonbeam has developed with Parity has led multiple parachains to offer Ethereum compatibility on their chains.
But there is an important catch. With the configuration described above, a user, for example, Alice, can have an Ethereum-style address (H160 format), which is 40+2 hex-characters long, in a Substrate based chain. This address matches a private key, which can be used to sign transactions in the Ethereum side of the chain. Furthermore, the address is mapped into a storage slot inside the Substrate Balance pallet to a Substrate-style address (H256 format).
However, Alice only knows the private key of the H160 address, and not of the mapped version. Therefore, she is unable to send transactions with her H256 address and is limited only to do read-only operations through Substrate’s API. As a consequence, Alice needs another H256 address matching a different private key to be able to operate in the Substrate side of the chain, which include, among others, staking, balances, and governance.
The following diagram illustrates this configuration.

This can creates friction and a poor user experience for Alice. First, she has to move tokens to her H160 mapped H256 address to be able to make transactions and deploy contracts through the EVM. Second, she also needs to hold a balance in her other H256 address (which she has a different private key for) to use Substrate-based features. So in short, Alice needs a minimum of two private keys to have the best of both worlds.
## Moonbeam Unified Accounts {: #moonbeam-unified-accounts }
Moonbeam’s focus is to create a fully Ethereum-compatible environment on Polkadot with the best user experience possible. This extends beyond the base Ethereum feature set, with additional features such as on-chain governance, staking, and cross-chain integrations.
With unified accounts, a user, for example, Bob, will only need a single H160 address, with its corresponding private key, to do everything we mentioned above, including both EVM and Substrate functions.
The diagram for this new configuration looks as follows.

That is it, Bob only holds one private key that matches one address. He does not need to move balances between 2 different accounts and is able to access all the features with a single account and private key. We have standardized this single account to conform to the Ethereum-style H160 address and ECDSA key standards.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/features/consensus/
--- BEGIN CONTENT ---
---
title: Moonbeam's Nimbus Consensus Framework
description: Learn about all the parts of Moonbeam's Nimbus consensus framework and how it works as part of Polkadot's shared security model.
categories: Basics
---
# Nimbus Parachain Consensus Framework
## Introduction {: #introduction }
Polkadot relies on a [hybrid consensus model](https://docs.polkadot.com/polkadot-protocol/architecture/polkadot-chain/pos-consensus/). In such a scheme, the block finality gadget and the block production mechanism are separate. Consequently, parachains only have to worry about producing blocks and rely on the relay chain to validate the state transitions.
At a parachain level, block producers are called [collators](https://wiki.polkadot.com/learn/learn-collator/). They maintain parachains (such as Moonbeam) by collecting transactions from users and offering blocks to the relay chain [validators](https://wiki.polkadot.com/learn/learn-validator/).
However, parachains might find the following problems they need to solve in a trustless and decentralized matter (if applicable):
- Amongst all of the nodes in the network, which ones are allowed to author blocks?
- If multiple nodes are allowed, will they be eligible at the same time? Only one? Maybe a few?
Enter Nimbus. Nimbus is a framework for building slot-based consensus algorithms on [Cumulus](https://github.com/paritytech/polkadot-sdk/tree/master/cumulus)-based parachains. It strives to provide standard implementations for the logistical parts of such consensus engines and helpful traits for implementing the elements (filters) that researchers and developers want to customize. These filters can be customizable to define what a block authorship slot is and can be composed, so block authorship is restricted to a subset of collators in multiple steps.
For example, Moonbeam uses a two-layer approach. The first layer comprises the parachain staking filter, which helps select an active collator pool among all collator candidates using a staked-based ranking. The second layer adds another filter which narrows down the number of collators to a subset for each slot.
Notice that Nimbus can only answer which collator(s) are eligible to produce a parachain block in the next available slot. It is the [Cumulus](https://docs.polkadot.com/develop/parachains/#cumulus) consensus mechanism that marks this parachain block as best, and ultimately the [BABE](https://docs.polkadot.com/polkadot-protocol/architecture/polkadot-chain/pos-consensus/#babe) and [GRANDPA](https://docs.polkadot.com/polkadot-protocol/architecture/polkadot-chain/pos-consensus/#grandpa-finality-gadget) hybrid consensus model (of the relay chain) that will include this parachain block in the relay chain and finalize it. Once any relay chain forks are resolved at a relay chain level, that parachain block is deterministically finalized.
The following two sections go over the filtering strategy currently used on Moonbeam.
## Parachain Staking Filtering {: #parachain-staking-filtering }
Collators can join the candidate pool by simply bonding some tokens via an extrinsic. Once in the pool, token holders can add to the candidate's stake via delegation (also referred to as staking), that is, at a parachain level.
Parachain staking is the first of the two Nimbus filters applied to the candidate pool. It selects the top {{ networks.moonbase.staking.max_candidates }} candidates in terms of tokens staked in the network, which includes the candidate's bond and delegations from token holders. This filtered pool is called selected candidates, and selected candidates are renewed every round (which lasts {{ networks.moonbase.staking.round_blocks }} blocks). For a given round, the following diagram describes the parachain staking filtering:

From this pool, another filter is applied to retrieve a subset of eligible candidates for the next block authoring slot.
If you want to learn more about staking, visit our [staking documentation](/learn/features/staking/).
## Fixed Size Subset Filtering {: #fixed-size-subset-filtering }
Once the parachain staking filter is applied and the selected candidates are retrieved, a second filter is applied on a block by block basis and helps narrow down the selected candidates to a smaller number of eligible collators for the next block authoring slot.
In broad terms, this second filter picks a pseudo-random subset of the previously selected candidates. The eligibility ratio, a tunable parameter, defines the size of this subset.
A high eligibility ratio results in fewer chances for the network to skip a block production slot, as more collators will be eligible to propose a block for a specific slot. However, only a certain number of validators are assigned to a parachain, meaning that most of these blocks will not be backed by a validator. For those that are, a higher number of backed blocks means that it might take longer for the relay chain to solve any possible forks and return a finalized block. Moreover, this might create an unfair advantage for certain collators that might be able to get their proposed block faster to relay chain validators, securing a higher portion of block rewards (if any).
A lower eligibility ratio might provide faster block finalization times and a fairer block production distribution amongst collators. However, if the eligible collators are not able to propose a block (for whatever reason), the network will skip a block, affecting its stability.
Once the size of the subset is defined, collators are randomly selected using a source of entropy. Currently, an internal coin-flipping algorithm is implemented, but this will later be migrated to use [Verifiable random function](https://docs.polkadot.com/polkadot-protocol/parachain-basics/randomness/){target=\_blank}. Consequently, a new subset of eligible collators is selected for every relay chain block. For a given round and a given block `XYZ`, the following diagram describes the fixed-size subset filtering:

## Why Nimbus? {: #why-nimbus }
You might ask yourself: but why Nimbus? Initially, it was not envisioned when Moonbeam was being developed. As Moonbeam progressed, the necessity for a more customizable but straightforward parachain consensus mechanism became clear, as the available methods presented some drawbacks or technical limitations.
With Nimbus, writing a parachain consensus engine is as easy as writing a pallet! This simplicity and flexibility is the main value it adds.
Some technical benefits of Nimbus are considered in the following sections.
### Weight and Extra Execution {: #weight-and-extra-execution }
Nimbus puts the author-checking execution in a [Substrate pallet](https://docs.polkadot.com/develop/parachains/customize-parachain/overview/). At first glance, you might think this adds a higher execution load to a single block compared to doing this check off-chain. But consider this from a validator’s perspective
The validators will also have to check the author. By putting the author-checking execution logic in a pallet, the execution time can be benchmarked and quantified with weights. If this execution time is not accounted for, there is the risk of a block exceeding the relay chain Wasm execution limit (currently 0.5 seconds).
In practice, this check will be fast and will most likely not push execution time over the limit. But from a theoretical perspective, accounting for its weight is better for implementation purposes.
### Reusability {: #reusability }
Another benefit of moving the author-checking execution to a pallet, rather than a custom executor, is that one single executor can be reused for any consensus that can be expressed in the Nimbus framework. That is slot-based, signature-sealed algorithms.
For example, the [relay-chain provided consensus](https://github.com/paritytech/polkadot-sdk/blob/master/cumulus/client/consensus/relay-chain/src/lib.rs), [AuRa](https://crates.io/crates/sc-consensus-aura) and [BABE](https://crates.io/crates/sc-consensus-babe) each have their own custom executor. With Nimbus, these consensus mechanisms can reuse the same executor. The power of reusability is evidenced by the Nimbus implementation of AuRa in less than 100 lines of code.
### Hot-Swapping Consensus {: #hot-swapping-consensus }
Teams building parachains may want to change, tune, or adjust their consensus algorithm from time to time. Without nimbus, swapping consensus would require a client upgrade and hard fork.
With the Nimbus framework, writing a consensus engine is as easy as writing a
[Substrate pallet](https://docs.polkadot.com/develop/parachains/customize-parachain/make-custom-pallet/). Consequently, swapping consensus is as easy as upgrading a pallet.
Nonetheless, hot swapping is still bounded by consensus engines (filters) that fit within Nimbus, but it might be helpful for teams that are yet confident on what consensus they want to implement in the long run.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/features/eth-compatibility/
--- BEGIN CONTENT ---
---
title: Ethereum Compatibility
description: Transitioning from Ethereum to Moonbeam? Here's a brief overview of the key components and key differences of Moonbeam's Ethereum compatibility.
categories: Basics
---
# Ethereum Compatibility
Moonbeam bridges the Ethereum and Polkadot ecosystems, offering developers the familiarity of Ethereum's tooling and infrastructure while leveraging Polkadot's scalability and interoperability.
This documentation overviews Moonbeam's Ethereum compatibility features and highlights its key components. It also covers some critical differences between Moonbeam and Ethereum so Ethereum developers know what to expect.
## Key Components {: #key-components }
### EVM Compatibility {: #evm }
Moonbeam incorporates a fully compatible EVM to execute smart contracts in Solidity or other EVM-compatible languages. This enables developers to deploy existing Ethereum smart contracts on Moonbeam with minimal modifications.
Learn more:
- [Moonbeam's Ethereum-compatibility architecture](/learn/platform/technology/#ethereum-compatibility-architecture){target=\_blank}
### Ethereum-style Accounts {: #ethereum-style-accounts }
Moonbeam employs H160 Ethereum-style accounts and ECDSA keys, ensuring compatibility with existing Ethereum wallets and facilitating a smooth end-user experience. This is possible due to Moonbeam's unified accounts system, which modifies the underlying Substrate account system to use Ethereum accounts by default.
Learn more:
- [Moonbeam's unified accounts system](/learn/core-concepts/unified-accounts/){target=\_blank}
### JSON-RPC Support {: #json-rpc-support }
Moonbeam offers full JSON-RPC compatibility with Ethereum, allowing developers to interact with Moonbeam nodes using familiar Ethereum tools and libraries. This compatibility extends to methods for account management, transaction submission, smart contract deployment, and event monitoring.
In addition to standard Ethereum RPC methods, Moonbeam supports non-standard Debug and Trace modules, providing developers with enhanced debugging and tracing capabilities for smart contract execution. The Debug module allows developers to inspect internal state transitions and execution traces, enabling efficient debugging of complex smart contracts. The Trace module provides detailed transaction traces, including opcode-level execution information and gas consumption, facilitating performance analysis and optimization.
Learn more:
- [Supported Ethereum RPC methods](/builders/ethereum/json-rpc/eth-rpc/){target=\_blank}
- [Subscribe to events with Ethereum JSON-RPC methods](/builders/ethereum/json-rpc/pubsub/){target=\_blank}
- [Debug and trace transactions with non-standard RPC methods](/builders/ethereum/json-rpc/debug-trace/){target=\_blank}
### Ethereum Developer Tools and Libraries {: #ethereum-dev-tools }
With the underlying support for Ethereum JSON-RPC methods, Moonbeam leverages Ethereum's rich ecosystem of developer libraries and environments. With seamless integration of popular Ethereum libraries and development environments, developers can leverage their existing knowledge and tooling to build and deploy decentralized applications (DApps) on Moonbeam.
Learn more:
- [Ethereum libraries](/builders/ethereum/libraries/){target=\_blank}
- [Ethereum development environments](/builders/ethereum/libraries/){target=\_blank}
### Precompiled Contracts {: #precompiled-contracts }
Moonbeam provides precompiled contracts that allow Ethereum smart contracts to seamlessly access Substrate functionality. These precompiled contracts expose Substrate features such as on-chain governance, staking, and identity management to Ethereum-based DApps on Moonbeam. This integration ensures that Ethereum developers can harness the full potential of Moonbeam's features, expanding the possibilities for dApp development on Moonbeam.
In addition, developers can leverage Ethereum MainNet precompiles seamlessly within their smart contracts on Moonbeam. These precompiled contracts, widely used on the Ethereum network, offer optimized and efficient execution of common cryptographic operations and complex computations. By supporting Ethereum MainNet precompiles, Moonbeam ensures compatibility with Ethereum-based dApps while enabling developers to utilize familiar tools and libraries to build on its platform.
Learn more:
- [Overview of the precompiled contracts on Moonbeam](/builders/ethereum/precompiles/overview/){target=\_blank}
### Ethereum Token Standards {: #ethereum-token-standards }
Moonbeam supports Ethereum token standards, allowing developers to deploy and interact with tokens that adhere to popular standards such as ERC-20, ERC-721, and ERC-1155. By supporting these standards, Moonbeam enables developers to deploy existing Ethereum tokens without modification.
Due to Moonbeam's native interoperability, ERC-20s can be sent cross-chain to other chains within the Polkadot ecosystem via Cross-Consensus Messaging (XCM).
Learn more:
- [Create common OpenZeppelin contracts such as ERC-20, ERC-721, and ERC-1155 tokens](/builders/ethereum/dev-env/openzeppelin/contracts/){target=\_blank}
- [XCM-enabled ERC-20s](/builders/interoperability/xcm/xc20/overview/#local-xc20s){target=\_blank} (also referred to as local XC-20s)
## Key Differences {: #key-differences }
### Consensus Mechanisms {: #consensus-mechanisms }
Moonbeam uses a Delegated Proof-of-Stake (DPoS) consensus mechanism, where token holders in the network can delegate candidates to become block producers, known as _collators_. On the other hand, Ethereum uses a Proof-of-Stake (PoS) system in which validators are selected based on their stake in the network to produce and validate blocks.
Learn more:
- [Differences between PoS and DPoS](/learn/core-concepts/consensus-finality/#main-differences){target=_blank}
### Finality {: #finality }
Moonbeam and Ethereum have different finality processes. On Ethereum, there is a checkpoint system where validators determine finality at checkpoint blocks, which takes at least 6.4 minutes for a block to be finalized. Moonbeam relies on Polkadot's [GRANDPA](https://docs.polkadot.com/polkadot-protocol/architecture/polkadot-chain/pos-consensus/#finality-gadget-grandpa){target=\_blank} finality gadget, which expedites finality by completing the process parallel to block production and allowing relay chain validators to vote on the highest block, finalizing all blocks leading up to that block.
Learn more:
- [Consensus and finality on Moonbeam](/learn/core-concepts/consensus-finality/){target=_blank}
### Proxy Accounts {: #proxy-accounts }
On both Moonbeam and Ethereum, accounts can be controlled by two main types of accounts: Externally Owned Accounts (EOA) or smart contracts. However, on Moonbeam, within both account types, there are also proxy accounts, which can perform a limited number of actions on behalf of another account.
Learn more:
- [An overview of proxy accounts](https://wiki.polkadot.com/learn/learn-proxies/){target=\_blank}
- [How to set up a proxy account](/tokens/manage/proxy-accounts/){target=\_blank}
### Account Balances {: #account-balances }
Balances on Ethereum are fairly straightforward; if an account holds tokens, that account has a token balance. On Moonbeam, different balance types exist to support various Substrate functionality. There are five types: free, reducible, reserved, miscellaneous frozen, and fee frozen. When using Ethereum tools, accounts show the reducible balance and don't include locked or frozen balances.
Learn more:
- [Moonbeam account balances](/learn/core-concepts/balances/){target=_blank}
### Balance Transfers {: #balance-transfers }
Since Moonbeam is a Substrate-based chain, balance transfers of the native asset (GLMR, MOVR, and DEV) can occur through the Ethereum and Substrate APIs. Like Ethereum, transfers sent through the Ethereum API rely on the `eth_sendRawTransaction`. Transfers sent through the Substrate API are done using the Balances Pallet, a built-in module in the Substrate framework that provides functionality for managing accounts and balances.
Learn more:
- [Balance transfers on Moonbeam](/learn/core-concepts/transfers-api/){target=_blank}
### Transaction Fees {: #transaction-fees }
Moonbeam and Ethereum calculate transaction fees differently due to variations in their underlying architectures and consensus mechanisms. The fundamental difference in how transaction fees are calculated is that Ethereum uses a gas-based fee system, and Moonbeam uses a weight-based system that maps to the gas used. Moonbeam also implements additional metrics in the underlying gas calculations, including proof size and storage costs.
Learn more:
- [Calculating transaction fees on Moonbeam](/learn/core-concepts/tx-fees/){target=\_blank}
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/features/governance/
--- BEGIN CONTENT ---
---
title: Governance
description: As a Polkadot parachain, Moonbeam uses an on-chain governance system, allowing for a stake-weighted vote on public referenda.
categories: Governance, Basics
---
# Governance on Moonbeam
## Introduction {: #introduction }
The goal of Moonbeam’s governance mechanism is to advance the protocol according to the desires of the community. In that shared mission, the governance process seeks to include all token holders. Any and all changes to the protocol must go through a referendum so that all token holders, weighted by stake, can have input on the decision.
Governance forums like the [Moonbeam Community Forum](https://forum.moonbeam.network){target=\_blank} and [Polkassembly](https://moonbeam.polkassembly.io/opengov){target=\_blank} enable open discussion and allow proposals to be refined based on community input. Autonomous enactments and [forkless upgrades](https://docs.polkadot.com/develop/parachains/maintenance/runtime-upgrades/#forkless-upgrades){target=\_blank} unite the community towards a shared mission to advance the protocol.
With the rollout of OpenGov (originally referred to as Gov2), the second phase of governance in Polkadot, several modifications have been introduced to the governance process. You can read the [OpenGov: What is Polkadot Gov2](https://moonbeam.network/news/opengov-what-is-polkadot-gov2){target=\_blank} blog post, which provides an overview of all of the changes made in OpenGov.
As of runtime 2400, all Moonbeam networks use OpenGov as their governance system.
## Principles {: #principles }
Guiding "soft" principles for engagement with Moonbeam's governance process include:
- Being inclusive to token holders that want to engage with Moonbeam and that are affected by governance decisions
- Favoring token holder engagement, even with views contrary to our own, versus a lack of engagement
- A commitment to openness and transparency in the decision-making process
- Working to keep the greater good of the network above personal gain
- Acting at all times as a moral agent that considers the consequences of action (or inaction) from a moral standpoint
- Being patient and generous in our interactions with other token holders, but not tolerating abusive or destructive language, actions, and behavior, and abiding by [Moonbeam’s Code of Conduct](https://github.com/moonbeam-foundation/code-of-conduct){target=\_blank}
These points were heavily inspired by Vlad Zamfir’s writings on governance. Refer to his articles, especially the [How to Participate in Blockchain Governance in Good Faith (and with Good Manners)](https://medium.com/@Vlad_Zamfir/how-to-participate-in-blockchain-governance-in-good-faith-and-with-good-manners-bd4e16846434){target=\_blank} Medium article.
## On-Chain Governance Mechanics {: #on-chain-governance-mechanics }
The "hard" governance process for Moonbeam will be driven by an on-chain process that allows the majority of tokens on the network to determine the outcomes of key decisions around the network. These decision points come in the form of stake-weighted voting on proposed referenda.
Some of the main components of this governance model include:
- **Referenda** — a stake-based voting scheme where each referendum is tied to a specific proposal for a change to the Moonbeam system including values for key parameters, code upgrades, or changes to the governance system itself
- **Voting** — referenda will be voted on by token holders on a stake-weighted basis. Referenda which pass are subject to delayed enactment so that people who disagree with the direction of the decision have time to exit the network
- **Council & Technical Committee Governance V1** — a group of community members who have special voting rights within the system. With the deprecation and removal of Governance v1, both of these committees were dissolved as of the [runtime 2800 release](https://forum.moonbeam.network/t/runtime-rt2801-schedule/1616/4){target=\_blank}
- **OpenGov Technical Committee** — a group of community members who can add certain proposals to the Whitelisted Track
For more details on how these Substrate frame pallets implement on-chain governance, you can checkout the [Walkthrough of Polkadot’s Governance](https://polkadot.com/blog/a-walkthrough-of-polkadots-governance){target=\_blank} blog post and the [Polkadot Governance Wiki](https://wiki.polkadot.com/learn/learn-polkadot-opengov/){target=\_blank}.
## Governance v2: OpenGov {: #opengov }
This section will cover everything you need to know about OpenGov on Moonbeam.
### General Definitions {: #general-definitions-gov2 }
- **Proposal** — an action or item, defined by the preimage hash, being proposed by a token holder and open for consideration and discussion by token holders
- **Referendum** — a proposal that is up for token-holder voting. Each referendum is tied to a specific proposal for a change to the Moonbeam system including values for key parameters, code upgrades, or changes to the governance system itself
- **Preimage hash** — hash of the proposal to be enacted. The first step to make a proposal is to submit a preimage. The hash is just its identifier. The proposer of the preimage can be different than the user that proposes that preimage as a formal proposal
- **Preimage deposit** — amount of tokens that the proposer needs to bond when submitting a preimage. It is calculated as the sum of a base deposit per network plus a fee per byte of the preimage being proposed
- **Origin** - an authorization-based dispatch source for an operation, which is used to determine the Track that a referendum is posted under
- **Track** - an Origin-specific pipeline that outlines the life cycle of proposals. Currently, there are five Tracks:
| Origin Track | Description | Referendum Examples |
|:-------------------:|:--------------------------------------------------------------------------------:|:--------------------------------------------------------------------:|
| Root | Highest privilege | Runtime upgrades, Technical Committee management |
| Whitelisted | Proposals to be whitelisted by the Technical Committee before being dispatched | Fast-tracked operations |
| General Admin | For general on-chain decisions | Changes to XCM fees, Orbiter program, Staking parameters, Registrars |
| Emergency Canceller | For cancellation of a referendum. Decision Deposit is refunded | Wrongly constructed referendum |
| Emergency Killer | For killing of bad/malicious referendum. Decision Deposit is slashed | Malicious referendum |
| Fast General Admin | For faster general on-chain decisions | HRMP channel management |
Tracks have different criteria parameters that are proportional to their level of Origin class. For example, more dangerous and privileged referenda will have more safeguards, higher thresholds, and longer consideration periods for approval. Please refer to the [Governance Parameters](#governance-parameters-v2) section for more information.
- **Voting** — a mechanism for token holders to support (Aye), oppose (Nay), or remain neutral (Abstain) on a proposal. For Aye and Nay, the voting weight is determined by both the number of tokens locked and the lock duration (Conviction). Abstain votes do not receive additional weighting
- **Conviction** — the time that token holders voluntarily lock their tokens when voting; the longer they are locked, the more weight their vote has
- **Lock balance** — the number of tokens that a user commits to a vote (note, this is not the same as a user's total account balance)
Moonbeam uses the concept of voluntary locking, which allows token holders to increase their voting power by locking tokens for a longer period of time. Specifying no Lock Period means a user's vote is valued at 10% of their lock balance. Specifying a greater Conviction increases voting power. For each increase in Conviction (vote multiplier), the Lock Periods double
- **Approval** — minimum "Aye" votes as a percentage of overall Conviction-weighted votes needed for approval
- **Support** — the minimum portion of Aye and Abstain votes (ignoring conviction) needed as a percentage of the total active supply for a proposal to pass. Nay votes do not count toward Support
- **Lead-in Period** — the initial proposal voting and discussion period. At this stage, proposals are in an undecided state until they pass some criteria for the given Track. The criteria include:
- **Prepare Period** — the minimum time the referendum needs to wait before it can progress to the next phase after submission
- **Capacity** — limit for the number of referenda on a given Track that can be decided at once
- **Decision Deposit** — the minimum deposit amount required for a referendum to progress to the decision phase after the end of the Lead-in Period. Since each Track has a defined Capacity, this deposit is larger than the submission deposit, and its goal is to mitigate spam
- **Decide Period** - token holders continue to vote on the referendum. If a referendum does not pass by the end of the period, it will be rejected, and the Decision Deposit will be refunded
- **Confirm Period** - a period of time within the Decide Period where the referendum needs to have maintained enough Approval and Support to be approved and move to the Enactment Period
- **Enactment Period** - a specified time, which is defined at the time the proposal was created, that an approved referendum waits before it can be dispatched. There is a minimum amount of time for each Track
- **Vote Delegation** — a voter can give their voting power, including Conviction voting, to another token holder (delegate), who may be more knowledgeable and able to make specific decisions
- **Multirole Delegation** — the ability to delegate voting power on a Track-by-Track basis, where a token holder can specify different delegates for each Track
### Governance Parameters {: #governance-parameters-v2 }
=== "Moonbeam"
| Variable | Value |
|:---------------------------:|:----------------------------------------------------------:|
| Preimage base deposit | {{ networks.moonbeam.preimage.base_deposit }} GLMR |
| Preimage deposit per byte | {{ networks.moonbeam.preimage.byte_deposit }} GLMR |
| Proposal Submission Deposit | {{ networks.moonbeam.governance.submission_deposit }} GLMR |
=== "Moonriver"
| Variable | Value |
|:---------------------------:|:-----------------------------------------------------------:|
| Preimage base deposit | {{ networks.moonriver.preimage.base_deposit }} MOVR |
| Preimage deposit per byte | {{ networks.moonriver.preimage.byte_deposit }} MOVR |
| Proposal Submission Deposit | {{ networks.moonriver.governance.submission_deposit }} MOVR |
=== "Moonbase Alpha"
| Variable | Value |
|:---------------------------:|:---------------------------------------------------------:|
| Preimage base deposit | {{ networks.moonbase.preimage.base_deposit }} DEV |
| Preimage deposit per byte | {{ networks.moonbase.preimage.byte_deposit }} DEV |
| Proposal Submission Deposit | {{ networks.moonbase.governance.submission_deposit }} DEV |
#### General Parameters by Track {: #general-parameters-by-track }
=== "Moonbeam"
| Track | Track ID | Capacity | Decision Deposit |
|:----------------------:|:--------:|:-----------------------------------------------------------------------------------:|:----------------------------------------------------------------------------------:|
| Root | 0 | {{ networks.moonbeam.governance.tracks.root.max_deciding }} proposals | {{ networks.moonbeam.governance.tracks.root.decision_deposit }} GLMR |
| Whitelisted | 1 | {{ networks.moonbeam.governance.tracks.whitelisted.max_deciding }} proposals | {{ networks.moonbeam.governance.tracks.whitelisted.decision_deposit }} GLMR |
| General Admin | 2 | {{ networks.moonbeam.governance.tracks.general_admin.max_deciding }} proposals | {{ networks.moonbeam.governance.tracks.general_admin.decision_deposit }} GLMR |
| Emergency Canceller | 3 | {{ networks.moonbeam.governance.tracks.canceller.max_deciding }} proposals | {{ networks.moonbeam.governance.tracks.canceller.decision_deposit }} GLMR |
| Emergency Killer | 4 | {{ networks.moonbeam.governance.tracks.killer.max_deciding }} proposals | {{ networks.moonbeam.governance.tracks.killer.decision_deposit }} GLMR |
| Fast General Admin | 5 | {{ networks.moonbeam.governance.tracks.fast_general_admin.max_deciding }} proposals | {{ networks.moonbeam.governance.tracks.fast_general_admin.decision_deposit }} GLMR |
=== "Moonriver"
| Track | Track ID | Capacity | Decision Deposit |
|:----------------------:|:--------:|:------------------------------------------------------------------------------------:|:-----------------------------------------------------------------------------------:|
| Root | 0 | {{ networks.moonriver.governance.tracks.root.max_deciding }} proposals | {{ networks.moonriver.governance.tracks.root.decision_deposit }} MOVR |
| Whitelisted | 1 | {{ networks.moonriver.governance.tracks.whitelisted.max_deciding }} proposals | {{ networks.moonriver.governance.tracks.whitelisted.decision_deposit }} MOVR |
| General Admin | 2 | {{ networks.moonriver.governance.tracks.general_admin.max_deciding }} proposals | {{ networks.moonriver.governance.tracks.general_admin.decision_deposit }} MOVR |
| Emergency Canceller | 3 | {{ networks.moonriver.governance.tracks.canceller.max_deciding }} proposals | {{ networks.moonriver.governance.tracks.canceller.decision_deposit }} MOVR |
| Emergency Killer | 4 | {{ networks.moonriver.governance.tracks.killer.max_deciding }} proposals | {{ networks.moonriver.governance.tracks.killer.decision_deposit }} MOVR |
| Fast General Admin | 5 | {{ networks.moonriver.governance.tracks.fast_general_admin.max_deciding }} proposals | {{ networks.moonriver.governance.tracks.fast_general_admin.decision_deposit }} MOVR |
=== "Moonbase Alpha"
| Track | Track ID | Capacity | Decision Deposit |
|:----------------------:|:--------:|:-----------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------:|
| Root | 0 | {{ networks.moonbase.governance.tracks.root.max_deciding }} proposals | {{ networks.moonbase.governance.tracks.root.decision_deposit }} DEV |
| Whitelisted | 1 | {{ networks.moonbase.governance.tracks.whitelisted.max_deciding }} proposals | {{ networks.moonbase.governance.tracks.whitelisted.decision_deposit }} DEV |
| General Admin | 2 | {{ networks.moonbase.governance.tracks.general_admin.max_deciding }} proposals | {{ networks.moonbase.governance.tracks.general_admin.decision_deposit }} DEV |
| Emergency Canceller | 3 | {{ networks.moonbase.governance.tracks.canceller.max_deciding }} proposals | {{ networks.moonbase.governance.tracks.canceller.decision_deposit }} DEV |
| Emergency Killer | 4 | {{ networks.moonbase.governance.tracks.killer.max_deciding }} proposals | {{ networks.moonbase.governance.tracks.killer.decision_deposit }} DEV |
| Fast General Admin | 5 | {{ networks.moonbase.governance.tracks.fast_general_admin.max_deciding }} proposals | {{ networks.moonbase.governance.tracks.fast_general_admin.decision_deposit }} DEV |
#### Period Parameters by Track {: #period-parameters-by-track }
=== "Moonbeam"
| Track | Prepare Period | Decide Period | Confirm Period | Minimum Enactment Period |
|:----------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
| Root | {{ networks.moonbeam.governance.tracks.root.prepare_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.root.prepare_period.time }}) | {{ networks.moonbeam.governance.tracks.root.decision_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.root.decision_period.time }}) | {{ networks.moonbeam.governance.tracks.root.confirm_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.root.confirm_period.time }}) | {{ networks.moonbeam.governance.tracks.root.min_enactment_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.root.min_enactment_period.time }}) |
| Whitelisted | {{ networks.moonbeam.governance.tracks.whitelisted.prepare_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.whitelisted.prepare_period.time }}) | {{ networks.moonbeam.governance.tracks.whitelisted.decision_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.whitelisted.decision_period.time }}) | {{ networks.moonbeam.governance.tracks.whitelisted.confirm_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.whitelisted.confirm_period.time }}) | {{ networks.moonbeam.governance.tracks.whitelisted.min_enactment_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.whitelisted.min_enactment_period.time }}) |
| General Admin | {{ networks.moonbeam.governance.tracks.general_admin.prepare_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.general_admin.prepare_period.time }}) | {{ networks.moonbeam.governance.tracks.general_admin.decision_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.general_admin.decision_period.time }}) | {{ networks.moonbeam.governance.tracks.general_admin.confirm_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.general_admin.confirm_period.time }}) | {{ networks.moonbeam.governance.tracks.general_admin.min_enactment_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.general_admin.min_enactment_period.time }}) |
| Emergency Canceller | {{ networks.moonbeam.governance.tracks.canceller.prepare_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.canceller.prepare_period.time }}) | {{ networks.moonbeam.governance.tracks.canceller.decision_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.canceller.decision_period.time }}) | {{ networks.moonbeam.governance.tracks.canceller.confirm_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.canceller.confirm_period.time }}) | {{ networks.moonbeam.governance.tracks.canceller.min_enactment_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.canceller.min_enactment_period.time }}) |
| Emergency Killer | {{ networks.moonbeam.governance.tracks.killer.prepare_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.killer.prepare_period.time }}) | {{ networks.moonbeam.governance.tracks.killer.decision_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.killer.decision_period.time }}) | {{ networks.moonbeam.governance.tracks.killer.confirm_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.killer.confirm_period.time }}) | {{ networks.moonbeam.governance.tracks.killer.min_enactment_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.killer.min_enactment_period.time }}) |
| Fast General Admin | {{ networks.moonbeam.governance.tracks.fast_general_admin.prepare_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.fast_general_admin.prepare_period.time }}) | {{ networks.moonbeam.governance.tracks.fast_general_admin.decision_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.fast_general_admin.decision_period.time }}) | {{ networks.moonbeam.governance.tracks.fast_general_admin.confirm_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.fast_general_admin.confirm_period.time }}) | {{ networks.moonbeam.governance.tracks.fast_general_admin.min_enactment_period.blocks }} blocks ({{ networks.moonbeam.governance.tracks.fast_general_admin.min_enactment_period.time }}) |
=== "Moonriver"
| Track | Prepare Period | Decide Period | Confirm Period | Minimum Enactment Period |
|:----------------------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
| Root | {{ networks.moonriver.governance.tracks.root.prepare_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.root.prepare_period.time }}) | {{ networks.moonriver.governance.tracks.root.decision_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.root.decision_period.time }}) | {{ networks.moonriver.governance.tracks.root.confirm_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.root.confirm_period.time }}) | {{ networks.moonriver.governance.tracks.root.min_enactment_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.root.min_enactment_period.time }}) |
| Whitelisted | {{ networks.moonriver.governance.tracks.whitelisted.prepare_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.whitelisted.prepare_period.time }}) | {{ networks.moonriver.governance.tracks.whitelisted.decision_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.whitelisted.decision_period.time }}) | {{ networks.moonriver.governance.tracks.whitelisted.confirm_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.whitelisted.confirm_period.time }}) | {{ networks.moonriver.governance.tracks.whitelisted.min_enactment_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.whitelisted.min_enactment_period.time }}) |
| General Admin | {{ networks.moonriver.governance.tracks.general_admin.prepare_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.general_admin.prepare_period.time }}) | {{ networks.moonriver.governance.tracks.general_admin.decision_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.general_admin.decision_period.time }}) | {{ networks.moonriver.governance.tracks.general_admin.confirm_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.general_admin.confirm_period.time }}) | {{ networks.moonriver.governance.tracks.general_admin.min_enactment_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.general_admin.min_enactment_period.time }}) |
| Emergency Canceller | {{ networks.moonriver.governance.tracks.canceller.prepare_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.canceller.prepare_period.time }}) | {{ networks.moonriver.governance.tracks.canceller.decision_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.canceller.decision_period.time }}) | {{ networks.moonriver.governance.tracks.canceller.confirm_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.canceller.confirm_period.time }}) | {{ networks.moonriver.governance.tracks.canceller.min_enactment_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.canceller.min_enactment_period.time }}) |
| Emergency Killer | {{ networks.moonriver.governance.tracks.killer.prepare_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.killer.prepare_period.time }}) | {{ networks.moonriver.governance.tracks.killer.decision_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.killer.decision_period.time }}) | {{ networks.moonriver.governance.tracks.killer.confirm_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.killer.confirm_period.time }}) | {{ networks.moonriver.governance.tracks.killer.min_enactment_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.killer.min_enactment_period.time }}) |
| Fast General Admin | {{ networks.moonriver.governance.tracks.fast_general_admin.prepare_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.fast_general_admin.prepare_period.time }}) | {{ networks.moonriver.governance.tracks.fast_general_admin.decision_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.fast_general_admin.decision_period.time }}) | {{ networks.moonriver.governance.tracks.fast_general_admin.confirm_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.fast_general_admin.confirm_period.time }}) | {{ networks.moonriver.governance.tracks.fast_general_admin.min_enactment_period.blocks }} blocks ({{ networks.moonriver.governance.tracks.fast_general_admin.min_enactment_period.time }}) |
=== "Moonbase Alpha"
| Track | Prepare Period | Decide Period | Confirm Period | Minimum Enactment Period |
|:----------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
| Root | {{ networks.moonbase.governance.tracks.root.prepare_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.root.prepare_period.time }}) | {{ networks.moonbase.governance.tracks.root.decision_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.root.decision_period.time }}) | {{ networks.moonbase.governance.tracks.root.confirm_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.root.confirm_period.time }}) | {{ networks.moonbase.governance.tracks.root.min_enactment_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.root.min_enactment_period.time }}) |
| Whitelisted | {{ networks.moonbase.governance.tracks.whitelisted.prepare_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.whitelisted.prepare_period.time }}) | {{ networks.moonbase.governance.tracks.whitelisted.decision_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.whitelisted.decision_period.time }}) | {{ networks.moonbase.governance.tracks.whitelisted.confirm_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.whitelisted.confirm_period.time }}) | {{ networks.moonbase.governance.tracks.whitelisted.min_enactment_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.whitelisted.min_enactment_period.time }}) |
| General Admin | {{ networks.moonbase.governance.tracks.general_admin.prepare_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.general_admin.prepare_period.time }}) | {{ networks.moonbase.governance.tracks.general_admin.decision_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.general_admin.decision_period.time }}) | {{ networks.moonbase.governance.tracks.general_admin.confirm_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.general_admin.confirm_period.time }}) | {{ networks.moonbase.governance.tracks.general_admin.min_enactment_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.general_admin.min_enactment_period.time }}) |
| Emergency Canceller | {{ networks.moonbase.governance.tracks.canceller.prepare_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.canceller.prepare_period.time }}) | {{ networks.moonbase.governance.tracks.canceller.decision_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.canceller.decision_period.time }}) | {{ networks.moonbase.governance.tracks.canceller.confirm_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.canceller.confirm_period.time }}) | {{ networks.moonbase.governance.tracks.canceller.min_enactment_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.canceller.min_enactment_period.time }}) |
| Emergency Killer | {{ networks.moonbase.governance.tracks.killer.prepare_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.killer.prepare_period.time }}) | {{ networks.moonbase.governance.tracks.killer.decision_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.killer.decision_period.time }}) | {{ networks.moonbase.governance.tracks.killer.confirm_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.killer.confirm_period.time }}) | {{ networks.moonbase.governance.tracks.killer.min_enactment_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.killer.min_enactment_period.time }}) |
| Fast General Admin | {{ networks.moonbase.governance.tracks.fast_general_admin.prepare_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.fast_general_admin.prepare_period.time }}) | {{ networks.moonbase.governance.tracks.fast_general_admin.decision_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.fast_general_admin.decision_period.time }}) | {{ networks.moonbase.governance.tracks.fast_general_admin.confirm_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.fast_general_admin.confirm_period.time }}) | {{ networks.moonbase.governance.tracks.fast_general_admin.min_enactment_period.blocks }} blocks ({{ networks.moonbase.governance.tracks.fast_general_admin.min_enactment_period.time }}) |
!!! note
As of runtime 3000, [asynchronous backing](https://wiki.polkadot.com/learn/learn-async-backing/#asynchronous-backing){target=\_blank} has been enabled on all Moonbeam networks. As a result, the target block time was reduced from 12 seconds to 6 seconds, which may break some timing-based assumptions.
#### Support and Approval Parameters by Track {: #support-and-approval-parameters-by-track }
=== "Moonbeam"
| Track | Approval Curve | Approval Parameters | Support Curve | Support Parameters |
|:----------------------:|:--------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
| Root | Reciprocal | {{ networks.moonbeam.governance.tracks.root.min_approval.time0 }}: {{ networks.moonbeam.governance.tracks.root.min_approval.percent0 }}% {{ networks.moonbeam.governance.tracks.root.min_approval.time1 }}: {{ networks.moonbeam.governance.tracks.root.min_approval.percent1 }}% {{ networks.moonbeam.governance.tracks.root.min_approval.time2 }}: {{ networks.moonbeam.governance.tracks.root.min_approval.percent2 }}% | Linear | {{ networks.moonbeam.governance.tracks.root.min_support.time0 }}: {{ networks.moonbeam.governance.tracks.root.min_support.percent0 }}% {{ networks.moonbeam.governance.tracks.root.min_support.time1 }}: {{ networks.moonbeam.governance.tracks.root.min_support.percent1 }}% |
| Whitelisted | Reciprocal | {{ networks.moonbeam.governance.tracks.whitelisted.min_approval.time0 }}: {{ networks.moonbeam.governance.tracks.whitelisted.min_approval.percent0 }}% {{ networks.moonbeam.governance.tracks.whitelisted.min_approval.time1 }}: {{ networks.moonbeam.governance.tracks.whitelisted.min_approval.percent1 }}% {{ networks.moonbeam.governance.tracks.whitelisted.min_approval.time2 }}: {{ networks.moonbeam.governance.tracks.whitelisted.min_approval.percent2 }}% | Reciprocal | {{ networks.moonbeam.governance.tracks.whitelisted.min_support.time0 }}: {{ networks.moonbeam.governance.tracks.whitelisted.min_support.percent0 }}% {{ networks.moonbeam.governance.tracks.whitelisted.min_support.time1 }}: {{ networks.moonbeam.governance.tracks.whitelisted.min_support.percent1 }}% {{ networks.moonbeam.governance.tracks.whitelisted.min_support.time2 }}: {{ networks.moonbeam.governance.tracks.whitelisted.min_support.percent2 }}% |
| General Admin | Reciprocal | {{ networks.moonbeam.governance.tracks.general_admin.min_approval.time0 }}: {{ networks.moonbeam.governance.tracks.general_admin.min_approval.percent0 }}% {{ networks.moonbeam.governance.tracks.general_admin.min_approval.time1 }}: {{ networks.moonbeam.governance.tracks.general_admin.min_approval.percent1 }}% {{ networks.moonbeam.governance.tracks.general_admin.min_approval.time2 }}: {{ networks.moonbeam.governance.tracks.general_admin.min_approval.percent2 }}% | Reciprocal | {{ networks.moonbeam.governance.tracks.general_admin.min_support.time0 }}: {{ networks.moonbeam.governance.tracks.general_admin.min_support.percent0 }}% {{ networks.moonbeam.governance.tracks.general_admin.min_support.time1 }}: {{ networks.moonbeam.governance.tracks.general_admin.min_support.percent1 }}% {{ networks.moonbeam.governance.tracks.general_admin.min_support.time2 }}: {{ networks.moonbeam.governance.tracks.general_admin.min_support.percent2 }}% |
| Emergency Canceller | Reciprocal | {{ networks.moonbeam.governance.tracks.canceller.min_approval.time0 }}: {{ networks.moonbeam.governance.tracks.canceller.min_approval.percent0 }}% {{ networks.moonbeam.governance.tracks.canceller.min_approval.time1 }}: {{ networks.moonbeam.governance.tracks.canceller.min_approval.percent1 }}% {{ networks.moonbeam.governance.tracks.canceller.min_approval.time2 }}: {{ networks.moonbeam.governance.tracks.canceller.min_approval.percent2 }}% | Reciprocal | {{ networks.moonbeam.governance.tracks.canceller.min_support.time0 }}: {{ networks.moonbeam.governance.tracks.canceller.min_support.percent0 }}% {{ networks.moonbeam.governance.tracks.canceller.min_support.time1 }}: {{ networks.moonbeam.governance.tracks.canceller.min_support.percent1 }}% {{ networks.moonbeam.governance.tracks.canceller.min_support.time2 }}: {{ networks.moonbeam.governance.tracks.canceller.min_support.percent2 }}% |
| Emergency Killer | Reciprocal | {{ networks.moonbeam.governance.tracks.killer.min_approval.time0 }}: {{ networks.moonbeam.governance.tracks.killer.min_approval.percent0 }}% {{ networks.moonbeam.governance.tracks.killer.min_approval.time1 }}: {{ networks.moonbeam.governance.tracks.killer.min_approval.percent1 }}% {{ networks.moonbeam.governance.tracks.killer.min_approval.time2 }}: {{ networks.moonbeam.governance.tracks.killer.min_approval.percent2 }}% | Reciprocal | {{ networks.moonbeam.governance.tracks.killer.min_support.time0 }}: {{ networks.moonbeam.governance.tracks.killer.min_support.percent0 }}% {{ networks.moonbeam.governance.tracks.killer.min_support.time1 }}: {{ networks.moonbeam.governance.tracks.killer.min_support.percent1 }}% {{ networks.moonbeam.governance.tracks.killer.min_support.time2 }}: {{ networks.moonbeam.governance.tracks.killer.min_support.percent2 }}% |
| Fast General Admin | Reciprocal | {{ networks.moonbeam.governance.tracks.fast_general_admin.min_approval.time0 }}: {{ networks.moonbeam.governance.tracks.fast_general_admin.min_approval.percent0 }}% {{ networks.moonbeam.governance.tracks.fast_general_admin.min_approval.time1 }}: {{ networks.moonbeam.governance.tracks.fast_general_admin.min_approval.percent1 }}% {{ networks.moonbeam.governance.tracks.fast_general_admin.min_approval.time2 }}: {{ networks.moonbeam.governance.tracks.fast_general_admin.min_approval.percent2 }}% | Reciprocal | {{ networks.moonbeam.governance.tracks.fast_general_admin.min_support.time0 }}: {{ networks.moonbeam.governance.tracks.fast_general_admin.min_support.percent0 }}% {{ networks.moonbeam.governance.tracks.fast_general_admin.min_support.time1 }}: {{ networks.moonbeam.governance.tracks.fast_general_admin.min_support.percent1 }}% {{ networks.moonbeam.governance.tracks.fast_general_admin.min_support.time2 }}: {{ networks.moonbeam.governance.tracks.fast_general_admin.min_support.percent2 }}% |
=== "Moonriver"
| Track | Approval Curve | Approval Parameters | Support Curve | Support Parameters |
|:----------------------:|:--------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
| Root | Reciprocal | {{ networks.moonriver.governance.tracks.root.min_approval.time0 }}: {{ networks.moonriver.governance.tracks.root.min_approval.percent0 }}% {{ networks.moonriver.governance.tracks.root.min_approval.time1 }}: {{ networks.moonriver.governance.tracks.root.min_approval.percent1 }}% {{ networks.moonriver.governance.tracks.root.min_approval.time2 }}: {{ networks.moonriver.governance.tracks.root.min_approval.percent2 }}% | Linear | {{ networks.moonriver.governance.tracks.root.min_support.time0 }}: {{ networks.moonriver.governance.tracks.root.min_support.percent0 }}% {{ networks.moonriver.governance.tracks.root.min_support.time1 }}: {{ networks.moonriver.governance.tracks.root.min_support.percent1 }}% |
| Whitelisted | Reciprocal | {{ networks.moonriver.governance.tracks.whitelisted.min_approval.time0 }}: {{ networks.moonriver.governance.tracks.whitelisted.min_approval.percent0 }}% {{ networks.moonriver.governance.tracks.whitelisted.min_approval.time1 }}: {{ networks.moonriver.governance.tracks.whitelisted.min_approval.percent1 }}% {{ networks.moonriver.governance.tracks.whitelisted.min_approval.time2 }}: {{ networks.moonriver.governance.tracks.whitelisted.min_approval.percent2 }}% | Reciprocal | {{ networks.moonriver.governance.tracks.whitelisted.min_support.time0 }}: {{ networks.moonriver.governance.tracks.whitelisted.min_support.percent0 }}% {{ networks.moonriver.governance.tracks.whitelisted.min_support.time1 }}: {{ networks.moonriver.governance.tracks.whitelisted.min_support.percent1 }}% {{ networks.moonriver.governance.tracks.whitelisted.min_support.time2 }}: {{ networks.moonriver.governance.tracks.whitelisted.min_support.percent2 }}% |
| General Admin | Reciprocal | {{ networks.moonriver.governance.tracks.general_admin.min_approval.time0 }}: {{ networks.moonriver.governance.tracks.general_admin.min_approval.percent0 }}% {{ networks.moonriver.governance.tracks.general_admin.min_approval.time1 }}: {{ networks.moonriver.governance.tracks.general_admin.min_approval.percent1 }}% {{ networks.moonriver.governance.tracks.general_admin.min_approval.time2 }}: {{ networks.moonriver.governance.tracks.general_admin.min_approval.percent2 }}% | Reciprocal | {{ networks.moonriver.governance.tracks.general_admin.min_support.time0 }}: {{ networks.moonriver.governance.tracks.general_admin.min_support.percent0 }}% {{ networks.moonriver.governance.tracks.general_admin.min_support.time1 }}: {{ networks.moonriver.governance.tracks.general_admin.min_support.percent1 }}% {{ networks.moonriver.governance.tracks.general_admin.min_support.time2 }}: {{ networks.moonriver.governance.tracks.general_admin.min_support.percent2 }}% |
| Emergency Canceller | Reciprocal | {{ networks.moonriver.governance.tracks.canceller.min_approval.time0 }}: {{ networks.moonriver.governance.tracks.canceller.min_approval.percent0 }}% {{ networks.moonriver.governance.tracks.canceller.min_approval.time1 }}: {{ networks.moonriver.governance.tracks.canceller.min_approval.percent1 }}% {{ networks.moonriver.governance.tracks.canceller.min_approval.time2 }}: {{ networks.moonriver.governance.tracks.canceller.min_approval.percent2 }}% | Reciprocal | {{ networks.moonriver.governance.tracks.canceller.min_support.time0 }}: {{ networks.moonriver.governance.tracks.canceller.min_support.percent0 }}% {{ networks.moonriver.governance.tracks.canceller.min_support.time1 }}: {{ networks.moonriver.governance.tracks.canceller.min_support.percent1 }}% {{ networks.moonriver.governance.tracks.canceller.min_support.time2 }}: {{ networks.moonriver.governance.tracks.canceller.min_support.percent2 }}% |
| Emergency Killer | Reciprocal | {{ networks.moonriver.governance.tracks.killer.min_approval.time0 }}: {{ networks.moonriver.governance.tracks.killer.min_approval.percent0 }}% {{ networks.moonriver.governance.tracks.killer.min_approval.time1 }}: {{ networks.moonriver.governance.tracks.killer.min_approval.percent1 }}% {{ networks.moonriver.governance.tracks.killer.min_approval.time2 }}: {{ networks.moonriver.governance.tracks.killer.min_approval.percent2 }}% | Reciprocal | {{ networks.moonriver.governance.tracks.killer.min_support.time0 }}: {{ networks.moonriver.governance.tracks.killer.min_support.percent0 }}% {{ networks.moonriver.governance.tracks.killer.min_support.time1 }}: {{ networks.moonriver.governance.tracks.killer.min_support.percent1 }}% {{ networks.moonriver.governance.tracks.killer.min_support.time2 }}: {{ networks.moonriver.governance.tracks.killer.min_support.percent2 }}% |
| Fast General Admin | Reciprocal | {{ networks.moonriver.governance.tracks.fast_general_admin.min_approval.time0 }}: {{ networks.moonriver.governance.tracks.fast_general_admin.min_approval.percent0 }}% {{ networks.moonriver.governance.tracks.fast_general_admin.min_approval.time1 }}: {{ networks.moonriver.governance.tracks.fast_general_admin.min_approval.percent1 }}% {{ networks.moonriver.governance.tracks.fast_general_admin.min_approval.time2 }}: {{ networks.moonriver.governance.tracks.fast_general_admin.min_approval.percent2 }}% | Reciprocal | {{ networks.moonriver.governance.tracks.fast_general_admin.min_support.time0 }}: {{ networks.moonriver.governance.tracks.fast_general_admin.min_support.percent0 }}% {{ networks.moonriver.governance.tracks.fast_general_admin.min_support.time1 }}: {{ networks.moonriver.governance.tracks.fast_general_admin.min_support.percent1 }}% {{ networks.moonriver.governance.tracks.fast_general_admin.min_support.time2 }}: {{ networks.moonriver.governance.tracks.fast_general_admin.min_support.percent2 }}% |
=== "Moonbase Alpha"
| Track | Approval Curve | Approval Parameters | Support Curve | Support Parameters |
|:----------------------:|:--------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
| Root | Reciprocal | {{ networks.moonbase.governance.tracks.root.min_approval.time0 }}: {{ networks.moonbase.governance.tracks.root.min_approval.percent0 }}% {{ networks.moonbase.governance.tracks.root.min_approval.time1 }}: {{ networks.moonbase.governance.tracks.root.min_approval.percent1 }}% {{ networks.moonbase.governance.tracks.root.min_approval.time2 }}: {{ networks.moonbase.governance.tracks.root.min_approval.percent2 }}% | Linear | {{ networks.moonbase.governance.tracks.root.min_support.time0 }}: {{ networks.moonbase.governance.tracks.root.min_support.percent0 }}% {{ networks.moonbase.governance.tracks.root.min_support.time1 }}: {{ networks.moonbase.governance.tracks.root.min_support.percent1 }}% |
| Whitelisted | Reciprocal | {{ networks.moonbase.governance.tracks.whitelisted.min_approval.time0 }}: {{ networks.moonbase.governance.tracks.whitelisted.min_approval.percent0 }}% {{ networks.moonbase.governance.tracks.whitelisted.min_approval.time1 }}: {{ networks.moonbase.governance.tracks.whitelisted.min_approval.percent1 }}% {{ networks.moonbase.governance.tracks.whitelisted.min_approval.time2 }}: {{ networks.moonbase.governance.tracks.whitelisted.min_approval.percent2 }}% | Reciprocal | {{ networks.moonbase.governance.tracks.whitelisted.min_support.time0 }}: {{ networks.moonbase.governance.tracks.whitelisted.min_support.percent0 }}% {{ networks.moonbase.governance.tracks.whitelisted.min_support.time1 }}: {{ networks.moonbase.governance.tracks.whitelisted.min_support.percent1 }}% {{ networks.moonbase.governance.tracks.whitelisted.min_support.time2 }}: {{ networks.moonbase.governance.tracks.whitelisted.min_support.percent2 }}% |
| General Admin | Reciprocal | {{ networks.moonbase.governance.tracks.general_admin.min_approval.time0 }}: {{ networks.moonbase.governance.tracks.general_admin.min_approval.percent0 }}% {{ networks.moonbase.governance.tracks.general_admin.min_approval.time1 }}: {{ networks.moonbase.governance.tracks.general_admin.min_approval.percent1 }}% {{ networks.moonbase.governance.tracks.general_admin.min_approval.time2 }}: {{ networks.moonbase.governance.tracks.general_admin.min_approval.percent2 }}% | Reciprocal | {{ networks.moonbase.governance.tracks.general_admin.min_support.time0 }}: {{ networks.moonbase.governance.tracks.general_admin.min_support.percent0 }}% {{ networks.moonbase.governance.tracks.general_admin.min_support.time1 }}: {{ networks.moonbase.governance.tracks.general_admin.min_support.percent1 }}% {{ networks.moonbase.governance.tracks.general_admin.min_support.time2 }}: {{ networks.moonbase.governance.tracks.general_admin.min_support.percent2 }}% |
| Emergency Canceller | Reciprocal | {{ networks.moonbase.governance.tracks.canceller.min_approval.time0 }}: {{ networks.moonbase.governance.tracks.canceller.min_approval.percent0 }}% {{ networks.moonbase.governance.tracks.canceller.min_approval.time1 }}: {{ networks.moonbase.governance.tracks.canceller.min_approval.percent1 }}% {{ networks.moonbase.governance.tracks.canceller.min_approval.time2 }}: {{ networks.moonbase.governance.tracks.canceller.min_approval.percent2 }}% | Reciprocal | {{ networks.moonbase.governance.tracks.canceller.min_support.time0 }}: {{ networks.moonbase.governance.tracks.canceller.min_support.percent0 }}% {{ networks.moonbase.governance.tracks.canceller.min_support.time1 }}: {{ networks.moonbase.governance.tracks.canceller.min_support.percent1 }}% {{ networks.moonbase.governance.tracks.canceller.min_support.time2 }}: {{ networks.moonbase.governance.tracks.canceller.min_support.percent2 }}% |
| Emergency Killer | Reciprocal | {{ networks.moonbase.governance.tracks.killer.min_approval.time0 }}: {{ networks.moonbase.governance.tracks.killer.min_approval.percent0 }}% {{ networks.moonbase.governance.tracks.killer.min_approval.time1 }}: {{ networks.moonbase.governance.tracks.killer.min_approval.percent1 }}% {{ networks.moonbase.governance.tracks.killer.min_approval.time2 }}: {{ networks.moonbase.governance.tracks.killer.min_approval.percent2 }}% | Reciprocal | {{ networks.moonbase.governance.tracks.killer.min_support.time0 }}: {{ networks.moonbase.governance.tracks.killer.min_support.percent0 }}% {{ networks.moonbase.governance.tracks.killer.min_support.time1 }}: {{ networks.moonbase.governance.tracks.killer.min_support.percent1 }}% {{ networks.moonbase.governance.tracks.killer.min_support.time2 }}: {{ networks.moonbase.governance.tracks.killer.min_support.percent2 }}% |
| Fast General Admin | Reciprocal | {{ networks.moonbase.governance.tracks.fast_general_admin.min_approval.time0 }}: {{ networks.moonbase.governance.tracks.fast_general_admin.min_approval.percent0 }}% {{ networks.moonbase.governance.tracks.fast_general_admin.min_approval.time1 }}: {{ networks.moonbase.governance.tracks.fast_general_admin.min_approval.percent1 }}% {{ networks.moonbase.governance.tracks.fast_general_admin.min_approval.time2 }}: {{ networks.moonbase.governance.tracks.fast_general_admin.min_approval.percent2 }}% | Reciprocal | {{ networks.moonbase.governance.tracks.fast_general_admin.min_support.time0 }}: {{ networks.moonbase.governance.tracks.fast_general_admin.min_support.percent0 }}% {{ networks.moonbase.governance.tracks.fast_general_admin.min_support.time1 }}: {{ networks.moonbase.governance.tracks.fast_general_admin.min_support.percent1 }}% {{ networks.moonbase.governance.tracks.fast_general_admin.min_support.time2 }}: {{ networks.moonbase.governance.tracks.fast_general_admin.min_support.percent2 }}% |
#### Conviction Multiplier {: #conviction-multiplier-v2 }
The Conviction multiplier is related to the number of Enactment Periods the tokens will be locked for after the referenda is enacted (if approved). Consequently, the longer you are willing to lock your tokens, the stronger your vote will be weighted. You also have the option of not locking tokens at all, but vote weight is drastically reduced (tokens are still locked during the duration of the referendum).
If you were to vote 1000 tokens with a 6x Conviction, your weighted vote would be 6000 units. That is, 1000 locked tokens multiplied by the Conviction, which in this scenario would be 6. On the other hand, if you decided you didn't want to have your tokens locked after enactment, you could vote your 1000 tokens with a 0.1x Conviction. In this case, your weighted vote would only be 100 units.
The Conviction multiplier values for each network are:
=== "Moonbeam"
| Lock Periods After Enactment | Conviction Multiplier | Approx. Lock Time |
|:----------------------------:|:---------------------:|:--------------------------------------------------------------:|
| 0 | 0.1 | None |
| 1 | 1 | {{networks.moonbeam.conviction.lock_period.conviction_1}} day |
| 2 | 2 | {{networks.moonbeam.conviction.lock_period.conviction_2}} days |
| 4 | 3 | {{networks.moonbeam.conviction.lock_period.conviction_3}} days |
| 8 | 4 | {{networks.moonbeam.conviction.lock_period.conviction_4}} days |
| 16 | 5 | {{networks.moonbeam.conviction.lock_period.conviction_5}} days |
| 32 | 6 | {{networks.moonbeam.conviction.lock_period.conviction_6}} days |
=== "Moonriver"
| Lock Periods After Enactment | Conviction Multiplier | Approx. Lock Time |
|:----------------------------:|:---------------------:|:---------------------------------------------------------------:|
| 0 | 0.1 | None |
| 1 | 1 | {{networks.moonriver.conviction.lock_period.conviction_1}} day |
| 2 | 2 | {{networks.moonriver.conviction.lock_period.conviction_2}} days |
| 4 | 3 | {{networks.moonriver.conviction.lock_period.conviction_3}} days |
| 8 | 4 | {{networks.moonriver.conviction.lock_period.conviction_4}} days |
| 16 | 5 | {{networks.moonriver.conviction.lock_period.conviction_5}} days |
| 32 | 6 | {{networks.moonriver.conviction.lock_period.conviction_6}} days |
=== "Moonbase Alpha"
| Lock Periods After Enactment | Conviction Multiplier | Approx. Lock Time |
|:----------------------------:|:---------------------:|:--------------------------------------------------------------:|
| 0 | 0.1 | None |
| 1 | 1 | {{networks.moonbase.conviction.lock_period.conviction_1}} day |
| 2 | 2 | {{networks.moonbase.conviction.lock_period.conviction_2}} days |
| 4 | 3 | {{networks.moonbase.conviction.lock_period.conviction_3}} days |
| 8 | 4 | {{networks.moonbase.conviction.lock_period.conviction_4}} days |
| 16 | 5 | {{networks.moonbase.conviction.lock_period.conviction_5}} days |
| 32 | 6 | {{networks.moonbase.conviction.lock_period.conviction_6}} days |
!!! note
The lock time approximations are based upon regular {{ networks.moonriver.block_time }}-second block times. Block production may vary and thus the displayed lock times should not be deemed exact.
### Roadmap of a Proposal {: #roadmap-of-a-proposal-v2 }
Before a proposal is submitted, the author of the proposal can submit their proposal idea to the designated Democracy Proposals section of the [Moonbeam Governance discussion forum](https://forum.moonbeam.network/c/governance/2){target=\_blank} for feedback from the community for at least five days. From there, the author can make adjustments to the proposal based on the feedback they've collected.
Once the author is ready, they can submit their proposal on-chain. To do so, first, they need to submit the preimage of the proposal. The submitter needs to bond a fee to store the preimage on-chain. The bond is returned once the submitter unnotes the preimage. Next, they can submit the actual proposal and pay the Submission Deposit, which is enough to cover the on-chain storage cost of the proposal. Then the Lead-in Period begins and the community can begin voting "Aye" or "Nay" on the proposal by locking tokens. In order for the referendum to advance and move out of the Lead-in Period to the Decide period, the following criteria must be met:
- The referendum must wait the duration of the Prepare Period, which allows for adequate time to discuss the proposal before it progresses to the next phase
- There is enough Capacity in the chosen Track
- A Decision Deposit has been made that meets the minimum requirements for the Track
If a referendum meets the above criteria, it moves to the Decide Period and takes up one of the spots in its designated Track. In the Decide Period, voting continues and the referendum has a set amount of days to reach the Approval and Support requirements needed for it to progress to the Confirm Period.
Once in the Confirm Period, a referendum must continuously meet the Approval and Support requirements for the duration of the period. If a referendum fails to meet the requirements at any point, it is returned to the Decide Period. If the referendum meets the Approval and Support requirements again, it can progress to the Confirm Period again and the Decide Period will be delayed until the end of the Confirm Period. If the Decide Period ends and not enough Approval and Support was received, the referendum will be rejected and the Decision Deposit will be returned. The proposal can be proposed again at any time.
If a referendum continuously receives enough Approval and Support during the Confirm Period, it will be approved and move to the Enactment Period. It will wait the duration of the Enactment Period before it gets dispatched.
The happy path for a proposal is shown in the following diagram:

### Proposal Example Walkthrough
A proposal (with its preimage) is submitted for the General Admin Track on Moonriver would have the following characteristics:
- The Approval curve starts at {{ networks.moonriver.governance.tracks.general_admin.min_approval.percent0 }}% on {{ networks.moonriver.governance.tracks.general_admin.min_approval.time0 }}, goes to {{ networks.moonriver.governance.tracks.general_admin.min_approval.percent1 }}% on {{ networks.moonriver.governance.tracks.general_admin.min_approval.time1 }}
- The Support curve starts at {{ networks.moonriver.governance.tracks.general_admin.min_support.percent0 }}% on {{ networks.moonriver.governance.tracks.general_admin.min_support.time0 }}, goes to {{ networks.moonriver.governance.tracks.general_admin.min_support.percent1 }}% on {{ networks.moonriver.governance.tracks.general_admin.min_support.time1 }}
- A referendum starts the Decide Period with 0% "Aye" votes (nobody voted in the Lead-in Period)
- Token holders begin to vote and the Approval increases to a value above {{ networks.moonriver.governance.tracks.general_admin.min_approval.percent1 }}% by {{ networks.moonriver.governance.tracks.general_admin.min_approval.time1 }}
- If the Approval and Support thresholds are met for the duration of the Confirm Period ({{ networks.moonriver.governance.tracks.general_admin.confirm_period.blocks }} blocks, approximately {{ networks.moonriver.governance.tracks.general_admin.confirm_period.time }}), the referendum is approved
- If the Approval and Support thresholds are not met during the Decision Period, the proposal is rejected. Note that the thresholds need to be met for the duration of the Confirm Period. Consequently, if they are met but the Decision Period expires before the completion of the Confirm Period, the proposal is rejected
The Approval and Support percentages can be calculated using the following:
=== "Approval"
```text
Approval = 100 * ( Total Conviction-weighted "Aye" votes / Total Conviction-weighted votes )
```
=== "Support"
```text
Support = 100 * ( Total Aye + Abstain votes, ignoring conviction / Total supply )
```
### Proposal Cancellations {: #proposal-cancellations }
In the event that a proposal already in the voting stage is found to have an issue, it may be necessary to prevent its approval. These instances may involve malicious activity or technical issues that make the changes impossible to implement due to recent upgrades to the network.
Cancellations must be voted on by the network to be executed. Cancellation proposals are faster than a typical proposal because they must be decided before the enactment of the proposal they seek to cancel, but they follow the same process as other referenda.
There is a cancellation Origin for use against referenda that contain an unforeseen problem, called the Emergency Canceller. The Emergency Canceller Origin and the Root Origin are allowed to cancel referenda. Regardless of the Origin, if a proposal is cancelled, it gets rejected and the Decision Deposit gets refunded.
In addition, there is a Kill Origin, which is for bad referenda intending to harm the network, called Emergency Killer. The Emergency Killer Origin and the Root Origin have the ability to kill referenda. In this case, a proposal is cancelled and the Decision Deposit is slashed, meaning the deposit amount is burned regardless of the Origin.
### Rights of the OpenGov Technical Committee {: #rights-of-the-opengov-technical-committee }
On Polkadot, the Technical Committee from Governance v1 was replaced with the Fellowship, which is a "mostly self-governing expert body with a primary goal of representing humans who embody and contain the technical knowledge base of the Kusama and/or Polkadot networks and protocol," according to [Polkadot's wiki](https://wiki.polkadot.com/general/web3-and-polkadot/#fellowship){target=\_blank}.
For Moonbeam's implementation of OpenGov, instead of the Fellowship, there is a community OpenGov Technical Committee that has very similar power to that of the Fellowship. Their power in governance resides in their ability to whitelist a proposal. OpenGov Technical Committee members may only vote to whitelist a proposal if whitelisting that proposal would protect against a security vulnerability to the network. The passing threshold of the OpenGov Technical Committee members on whether to whitelist a proposal is determined by governance. As such, the OpenGov Technical Committee has very limited power over the network. Its purpose is to provide technical review of urgent security issues that are proposed by token holders.
While still subject to governance, the idea behind the Whitelist track is that it will have different parameters to make it faster for proposals to pass. The Whitelist Track parameters, including approval, support, and voting, are determined by the Moonriver or Moonbeam token holders through governance and cannot be changed by the OpenGov Technical Committee.
The OpenGov Technical Committee is made up of members of the community who have technical knowledge and expertise in Moonbeam-based networks.
### Related Guides on OpenGov {: #try-it-out }
For related guides on submitting and voting on referenda on Moonbeam with OpenGov, please check the following guides:
- [How to Submit a Proposal](/tokens/governance/proposals/){target=\_blank}
- [How to Vote on a Proposal](/tokens/governance/voting/){target=\_blank}
- [Interact with the Preimages Precompiled Contract (Solidity Interface)](/builders/ethereum/precompiles/features/governance/preimage/){target=\_blank}
- [Interact with the Referenda Precompiled Contract (Solidity Interface)](/builders/ethereum/precompiles/features/governance/referenda/){target=\_blank}
- [Interact with the Conviction Voting Precompiled Contract (Solidity Interface)](/builders/ethereum/precompiles/features/governance/conviction-voting/){target=\_blank}
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/features/randomness/
--- BEGIN CONTENT ---
---
title: Randomness
description: Learn about the sources of VRF randomness on Moonbeam, the request and fulfillment process, and some security considerations when using on-chain randomness.
categories: Basics
---
# Randomness on Moonbeam
## Introduction {: #introduction }
Randomness is necessary for a variety of blockchain applications to create unbiased, unpredictable, and unique outcomes. However, obtaining a reliable source of randomness is a challenge. Computers are deterministic, meaning given the same input, the same output will always be produced. Therefore, random values generated by computers are referred to as pseudo-random as they appear to be statistically random, but given the same input, the output can easily be repeated.
Moonbeam utilizes verifiable random functions (VRF) to generate randomness that can be verified on-chain. A VRF is a cryptographic function that takes some input and produces random values, along with a proof of authenticity that they were generated by the submitter. The proof can be verified by anyone to ensure that the random values were generated correctly.
There are two available sources of randomness that provide random inputs based on block producers' VRF keys and past randomness results: [local VRF](#local-vrf) and [BABE epoch randomness](#babe-epoch-randomness). Local VRF is determined directly within Moonbeam using the collator of the block's VRF key and the last block's VRF output. On the other hand, [BABE](https://docs.polkadot.com/polkadot-protocol/architecture/polkadot-chain/pos-consensus/#block-production-babe){target=\_blank} epoch randomness is based on all the VRF produced by the relay chain validators during a complete [epoch](https://wiki.polkadot.com/general/glossary/#epoch){target=\_blank}.
You can interact with and request on-chain randomness using the Randomness Precompile contract, a Solidity interface that enables smart contract developers to access the randomness functionality through the Ethereum API. For more information, please check out the [Interacting with the Randomness Precompile](/builders/ethereum/precompiles/features/randomness/){target=\_blank} guide. You can also take a look at the [Randomness Pallet](/builders/substrate/interfaces/features/randomness/){target=\_blank}, which can be used to obtain current randomness requests and results.
## General Definitions {: #general-definitions }
- **Epoch** - a time duration in the BABE protocol that is broken into smaller time slots. Slots are discrete units of time six seconds in length. On Polkadot, one epoch lasts approximately 2,400 slots or 4 hours. On Kusama, one epoch lasts approximately 600 slots or 1 hour.
- **Deposit** - an amount of funds required to request random words. There is one deposit per request. Once the request has been fulfilled, the deposit will be returned to the account that requested the randomness
- **Block expiration delay** - the number of blocks that must pass before a local VRF request expires and can be purged
- **Epoch expiration delay** - the number of epochs that must pass before a BABE request expires and can be purged
- **Minimum block delay** - the minimum number of blocks before a request can be fulfilled for local VRF requests
- **Maximum block delay** - the maximum number of blocks before a request can be fulfilled for local VRF requests
- **Maximum random words** - the maximum number of random words being requested
- **Epoch fulfillment delay** - the delay in epochs before a request can be fulfilled for a BABE request
## Quick Reference {: #quick-reference }
=== "Moonbeam"
| Variable | Value |
|:-----------------------:|:---------------------------------------------------------------------------------------------:|
| Deposit | {{ networks.moonbeam.randomness.req_deposit_amount.glmr }} GLMR |
| Block expiration delay | {{ networks.moonbeam.randomness.block_expiration }} blocks |
| Epoch expiration delay | {{ networks.moonbeam.randomness.epoch_expiration }} epochs |
| Minimum block delay | {{ networks.moonbeam.randomness.min_vrf_blocks_delay }} blocks |
| Maximum block delay | {{ networks.moonbeam.randomness.max_vrf_blocks_delay }} blocks |
| Maximum random words | {{ networks.moonbeam.randomness.max_random_words }} words |
| Epoch fulfillment delay | {{ networks.moonbeam.randomness.epoch_fulfillment_delay }} epochs (following the current one) |
=== "Moonriver"
| Variable | Value |
|:-----------------------:|:----------------------------------------------------------------------------------------------:|
| Deposit | {{ networks.moonriver.randomness.req_deposit_amount.movr }} MOVR |
| Block expiration delay | {{ networks.moonriver.randomness.block_expiration }} blocks |
| Epoch expiration delay | {{ networks.moonriver.randomness.epoch_expiration }} epochs |
| Minimum block delay | {{ networks.moonriver.randomness.min_vrf_blocks_delay }} blocks |
| Maximum block delay | {{ networks.moonriver.randomness.max_vrf_blocks_delay }} blocks |
| Maximum random words | {{ networks.moonriver.randomness.max_random_words }} words |
| Epoch fulfillment delay | {{ networks.moonriver.randomness.epoch_fulfillment_delay }} epochs (following the current one) |
=== "Moonbase Alpha"
| Variable | Value |
|:-----------------------:|:---------------------------------------------------------------------------------------------:|
| Deposit | {{ networks.moonbase.randomness.req_deposit_amount.dev }} DEV |
| Block expiration delay | {{ networks.moonbase.randomness.block_expiration }} blocks |
| Epoch expiration delay | {{ networks.moonbase.randomness.epoch_expiration }} epochs |
| Minimum block delay | {{ networks.moonbase.randomness.min_vrf_blocks_delay }} blocks |
| Maximum block delay | {{ networks.moonbase.randomness.max_vrf_blocks_delay }} blocks |
| Maximum random words | {{ networks.moonbase.randomness.max_random_words }} words |
| Epoch fulfillment delay | {{ networks.moonbase.randomness.epoch_fulfillment_delay }} epochs (following the current one) |
## Local VRF {: #local-vrf }
Local VRF randomness is generated on a block-by-block basis at the beginning of the block using the previous block's VRF output along with the public key of the current block author's VRF key. The generated randomness result is stored and used to fulfill all randomness requests for the current block.
You can request local VRF randomness using the [`requestLocalVRFRandomWords` method](/builders/ethereum/precompiles/features/randomness/#:~:text=requestLocalVRFRandomWords){target=\_blank} of the [Randomness Precompile](/builders/ethereum/precompiles/features/randomness/){target=\_blank}.
If your contract could have concurrent requests open, you can use the `requestId` returned from the `requestLocalVRFRandomWords` method to track which response is associated with which randomness request.
## BABE Epoch Randomness {: #babe-epoch-randomness }
BABE epoch randomness is based on a hash of the VRF values from the blocks produced in the relay chain epoch before last. On Polkadot, an [epoch lasts for roughly 4 hours](https://wiki.polkadot.com/learn/learn-cryptography/#vrf){target=\_blank}, and on Kusama, an [epoch lasts for roughly 1 hour](https://guide.kusama.network/docs/maintain-polkadot-parameters#periods-of-common-actions-and-attributes){target=\_blank}. The hashing is completed on the relay chain, and as such, it is not possible for a collator on Moonbeam to influence the randomness value unless they are also a validator on the relay chain and were responsible for producing the last output included in an epoch.
The randomness remains constant during an epoch. If a collator skips block production, the next eligible collator can fulfill the request using the same random value.
You can request BABE epoch randomness using the [`requestRelayBabeEpochRandomWords` method](/builders/ethereum/precompiles/features/randomness/#:~:text=requestRelayBabeEpochRandomWords){target=\_blank} of the [Randomness Precompile](/builders/ethereum/precompiles/features/randomness/){target=\_blank}. In order to generate unique randomness, a different salt must be provided to the `requestRelayBabeEpochRandomWords` function.
At the beginning of each relay chain epoch change, the randomness from one epoch ago is read from the relay chain state proof and used to fulfill all randomness requests that are due in the current block.
## Request & Fulfill Process {: #request-and-fulfill-process }
In general, the request and fulfill process for randomness is as follows:
1. Pay the deposit required to request random words
2. Request the randomness either using the local VRF or BABE epoch source of randomness. When requesting randomness you'll need to specify a few things:
- a refund address where any excess fees will be sent to
- the amount of fees which will be set aside to pay for fulfillment. If the specified amount is not enough you can always increase the request fees later, or if it's more than enough you'll be refunded the excess fees to the specified address after fulfillment
- a unique salt that will be used to generate different random words
- the number of random words you would like to request
- for local VRF, the delay period in blocks, which is used to increase unpredictability. It must be between the [minimum and maximum number of blocks](#quick-reference) as listed above. For BABE epoch randomness, you do not need to specify a delay but can fulfill the request after the [epoch delay](#quick-reference) has passed
3. Wait for the delay period to pass
4. Fulfill the randomness request, which triggers the random words to be computed using the current block's randomness result and the given salt. This can manually be done by anyone using the fee that was initially set aside for the request
5. For fulfilled requests, the random words are returned and the cost of execution will be refunded from the request fee to the address that initiated the fulfillment. Then any excess fees and the request deposit are transferred to the specified refund address
If a request expires it can be purged by anyone. When this happens, the request fee is paid out to the address that initiated the purge and the deposit is returned to the original requester.
The happy path for a randomness request is shown in the following diagram:

## Security Considerations {: #security-considerations }
A method with the ability to call your `fulfillRandomness` method directly could spoof a VRF response with any random value, so it's critical that it can only be directly called by the `RandomnessConsumer.sol` contract's `rawFulfillRandomness` method.
For your users to trust that your contract's random behavior is free from malicious interference, it's best if you can write it so that all behaviors implied by a VRF response are executed *during* your `fulfillRandomness` method. If your contract must store the response (or anything derived from it) and use it later, you must ensure that any user-significant behavior which depends on that stored value cannot be manipulated by a subsequent VRF request.
Similarly, the collators have some influence over the order in which VRF responses appear on the blockchain, so if your contract could have multiple VRF requests in flight simultaneously, you must ensure that the order in which the VRF responses arrive cannot be used to manipulate your contract's user-significant behavior.
Since the output of the random words generated for `requestLocalVRFRandomWords` is dependent on the collator producing the block at fulfillment, the collator could skip its block, forcing the fulfillment to be executed by a different collator and therefore generating a different VRF. However, such an attack would incur the cost of losing the block reward to the collator. It is also possible for a collator to be able to predict some of the possible outcome of the VRF if the delay between the request and the fulfillment is too short. It is for this reason that you can choose to provide a higher delay.
Since the output of the random words generated for `requestRelayBabeEpochRandomWords` is dependent on the relay chain validator producing the blocks during an epoch, it is possible for the last validator of an epoch to choose between two possible VRF outputs by skipping the production of a block. However, such an attack would incur the cost of losing the block reward to the validator. It is not possible for a parachain collator to predict or influence the output of the relay chain VRF, not to censor the fulfillment, as long as there is one honest collator.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/features/staking/
--- BEGIN CONTENT ---
---
title: Staking
description: Moonbeam provides staking features where token holders delegate collator candidates with their tokens and earn rewards.
categories: Basics, Staking
---
# Staking on Moonbeam
## Introduction {: #introduction }
Moonbeam uses a block production mechanism based on [Polkadot's Proof-of-Stake model](https://docs.polkadot.com/polkadot-protocol/architecture/polkadot-chain/pos-consensus/){target=\_blank}, where there are collators and validators. [Collators](https://wiki.polkadot.com/learn/learn-collator/){target=\_blank} maintain parachains (in this case, Moonbeam) by collecting transactions from users and producing state transition proofs for the relay chain [validators](https://wiki.polkadot.com/learn/learn-validator/){target=\_blank}.
The candidates in the active set of collators (nodes that produce blocks) are selected based on their stake in the network. And here is where staking comes in.
Collator candidates (and token holders if they delegate) have a stake in the network. The top N candidates by staked amount are chosen to produce blocks with a valid set of transactions, where N is a configurable parameter. Part of each block reward goes to the collators that produced the block, who then share it with the delegators considering their percental contributions towards the collator's stake. In such a way, network members are incentivized to stake tokens to improve the overall security. Since staking is done at a protocol level through the staking interface, if you choose to delegate, the collators you delegate to do not have access to your tokens.
To easily manage staking related actions, you can visit the [Moonbeam Network DApp](https://apps.moonbeam.network){target=\_blank} and use the network tabs at the top of the page to easily switch between Moonbeam networks. To learn how to use the DApp, you can check out the [How to Stake MOVR Tokens](https://moonbeam.network/news/how-to-stake-movr-tokens-on-moonriver-and-earn-staking-rewards){target=\_blank} guide or [video tutorial](https://www.youtube.com/watch?v=8GwetYmzEJM){target=\_blank}, both of which can be adapted for the Moonbeam and the Moonbase Alpha TestNet.
## General Definitions {: #general-definitions }
Some important parameters to understand in relation to the staking system on Moonbeam include:
- **Round** — a specific number of blocks around which staking actions are enforced. For example, new delegations are enacted when the next round starts. When bonding less or revoking delegations, funds are returned after a specified number of rounds
- **Candidates** - node operators that are eligible to become block producers if they can acquire enough stake to be in the active set
- **Collators** — active set of candidates that are selected to be block producers. They collect transactions from users and produce state transition proofs for the relay chain to validate
- **Delegators** — token holders who stake tokens, vouching for specific collator candidates. Any user that holds a minimum amount of tokens as [free balance](https://wiki.polkadot.com/learn/learn-accounts/#balance-types#balance-types) can become a delegator
- **Minimum delegation per candidate** — minimum amount of tokens to delegate candidates once a user is in the set of delegators
- **Maximum delegators per candidate** — maximum number of delegators, by staked amount, that a candidate can have which are eligible to receive staking rewards
- **Maximum delegations** — maximum number of candidates a delegator can delegate
- **Exit delay** - an exit delay is the amount of rounds before a candidate or delegator can execute a scheduled request to decrease or revoke a bond, or leave the set of candidates or delegators
- **Reward payout delay** - a certain amount of rounds must pass before staking rewards are distributed automatically to the free balance
- **Reward pool** - a portion of the annual inflation that is set aside for collators and delegators
- **Collator commission** - default fixed percent a collator takes off the top of the due staking rewards. Not related to the reward pool
- **Delegator rewards** — the aggregate delegator rewards distributed over all eligible delegators, taking into account the relative size of stakes ([read more](/learn/features/staking/#reward-distribution))
- **Auto-compounding** - a setting that automatically applies a percentage of a delegator's rewards to their total amount delegated
- **Slashing** — a mechanism to discourage collator misbehavior, where typically the collator and their delegators get slashed by losing a percentage of their stake. Currently, there is no slashing but this can be changed through governance. Collators who produce blocks that are not finalized by the relay chain won't receive rewards
## Quick Reference {: #quick-reference }
=== "Moonbeam"
| Variable | Value |
|:--------------------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------------------:|
| Round duration | {{ networks.moonbeam.staking.round_blocks }} blocks ({{ networks.moonbeam.staking.round_hours }} hours) |
| Minimum delegation per candidate | {{ networks.moonbeam.staking.min_del_stake }} GLMR |
| Maximum delegators per candidate | {{ networks.moonbeam.staking.max_del_per_can }} |
| Maximum delegations | {{ networks.moonbeam.staking.max_del_per_del }} |
| Reward payout delay | {{ networks.moonbeam.delegator_timings.rewards_payouts.rounds }} rounds ({{ networks.moonbeam.delegator_timings.rewards_payouts.hours }} hours) |
| Add or increase delegation | takes effect in the next round (funds are withdrawn immediately) |
| Decrease delegation delay | {{ networks.moonbeam.delegator_timings.del_bond_less.rounds }} rounds ({{ networks.moonbeam.delegator_timings.del_bond_less.hours }} hours) |
| Revoke delegations delay | {{ networks.moonbeam.delegator_timings.revoke_delegations.rounds }} rounds ({{ networks.moonbeam.delegator_timings.revoke_delegations.hours }} hours) |
| Leave delegators delay | {{ networks.moonbeam.delegator_timings.leave_delegators.rounds }} rounds ({{ networks.moonbeam.delegator_timings.leave_delegators.hours }} hours) |
=== "Moonriver"
| Variable | Value |
|:--------------------------------:|:-------------------------------------------------------------------------------------------------------------------------------------------------------:|
| Round duration | {{ networks.moonriver.staking.round_blocks }} blocks ({{ networks.moonriver.staking.round_hours }} hours) |
| Minimum delegation per candidate | {{ networks.moonriver.staking.min_del_stake }} MOVR |
| Maximum delegators per candidate | {{ networks.moonriver.staking.max_del_per_can }} |
| Maximum delegations | {{ networks.moonriver.staking.max_del_per_del }} |
| Reward payout delay | {{ networks.moonriver.delegator_timings.rewards_payouts.rounds }} rounds ({{ networks.moonriver.delegator_timings.rewards_payouts.hours }} hours) |
| Add or increase delegation | takes effect in the next round (funds are withdrawn immediately) |
| Decrease delegation delay | {{ networks.moonriver.delegator_timings.del_bond_less.rounds }} rounds ({{ networks.moonriver.delegator_timings.del_bond_less.hours }} hours) |
| Revoke delegations delay | {{ networks.moonriver.delegator_timings.revoke_delegations.rounds }} rounds ({{ networks.moonriver.delegator_timings.revoke_delegations.hours }} hours) |
| Leave delegators delay | {{ networks.moonriver.delegator_timings.leave_delegators.rounds }} rounds ({{ networks.moonriver.delegator_timings.leave_delegators.hours }} hours) |
=== "Moonbase Alpha"
| Variable | Value |
|:--------------------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------------------:|
| Round duration | {{ networks.moonbase.staking.round_blocks }} blocks ({{ networks.moonbase.staking.round_hours }} hours) |
| Minimum delegation per candidate | {{ networks.moonbase.staking.min_del_stake }} DEV |
| Maximum delegators per candidate | {{ networks.moonbase.staking.max_del_per_can }} |
| Maximum delegations | {{ networks.moonbase.staking.max_del_per_del }} |
| Reward payout delay | {{ networks.moonbase.delegator_timings.rewards_payouts.rounds }} rounds ({{ networks.moonbase.delegator_timings.rewards_payouts.hours }} hours) |
| Add or increase delegation | takes effect in the next round (funds are withdrawn immediately) |
| Decrease delegation delay | {{ networks.moonbase.delegator_timings.del_bond_less.rounds }} rounds ({{ networks.moonbase.delegator_timings.del_bond_less.hours }} hours) |
| Revoke delegations delay | {{ networks.moonbase.delegator_timings.revoke_delegations.rounds }} rounds ({{ networks.moonbase.delegator_timings.revoke_delegations.hours }} hours) |
| Leave delegators delay | {{ networks.moonbase.delegator_timings.leave_delegators.rounds }} rounds ({{ networks.moonbase.delegator_timings.leave_delegators.hours }} hours) |
!!! note
As of runtime 3000, [asynchronous backing](https://wiki.polkadot.com/learn/learn-async-backing/#asynchronous-backing){target=\_blank} has been enabled on all Moonbeam networks. As a result, the target block time was reduced from 12 seconds to 6 seconds, which may break some timing-based assumptions.
To learn how to get the current value of any of the parameters around staking, check out the [Retrieving Staking Parameters](/tokens/staking/stake/#retrieving-staking-parameters){target=\_blank} section of the [How to Stake your Tokens](/tokens/staking/stake/){target=\_blank} guide.
If you're looking for candidate or collator-specific requirements and information, you can take a look at the [Collators](/node-operators/networks/collators/requirements/#bonding-requirements){target=\_blank} guide.
## Resources for Selecting a Collator {: #resources-for-selecting-a-collator}
There are a few resources you can check out to help you select a collator to delegate:
=== "Moonbeam"
| Variable | Value |
|:----------------------------:|:-------------------------------------------------------------------------------:|
| Stake GLMR Dashboard | [Stake GLMR](https://stakeglmr.com){target=\_blank} |
| Collators Leaderboard | [Moonscan](https://moonbeam.moonscan.io/collators){target=\_blank} |
| Collator Dashboard | [DappLooker](https://dapplooker.com/dashboard/moonbeam-collator-dashboard-91){target=\_blank} |
=== "Moonriver"
| Variable | Value |
|:----------------------------:|:--------------------------------------------------------------------------------:|
| Stake MOVR Dashboard | [Stake MOVR](https://stakemovr.com){target=\_blank} |
| Collators Leaderboard | [Moonscan](https://moonriver.moonscan.io/collators){target=\_blank} |
| Collator Dashboard | [DappLooker](https://dapplooker.com/dashboard/moonriver-collator-dashboard-28){target=\_blank} |
=== "Moonbase Alpha"
| Variable | Value |
|:------------------:|:--------------------------------------------------------------------------------:|
| List of candidates | [Moonbase Alpha Subscan](https://moonbase.subscan.io/validator){target=\_blank} |
!!! note
The DappLooker Collator dashboard for Moonriver is experimental beta software and may not accurately reflect collator performance. Be sure to do your own research before delegating to a collator.
### General Tips {: #general-tips }
- To optimize your staking rewards, you should generally choose a collator with a lower total amount bonded. In that case, your delegation amount will represent a larger portion of the collator’s total stake and you will earn proportionally higher rewards. However, there is a higher risk of the collator being kicked out of the active set and not earning rewards at all
- The minimum bond for each collator tends to increase over time, so if your delegation is close to the minimum, there is a higher chance you might fall below the minimum and not receive rewards
- Spreading delegations between multiple collators is more efficient in terms of rewards, but only recommended if you have enough to stay above the minimum bond of each collator
- You can consider collator performance by reviewing the number of blocks each collator has produced recently
- You can set up auto-compounding which will automatically restake a specified percentage of your delegation rewards
## Reward Distribution {: #reward-distribution }
Rewards for collators and their delegators are calculated at the start of every round for their work prior to the [reward payout delay](#quick-reference). For example, on Moonriver the rewards are calculated for the collators work from {{ networks.moonriver.delegator_timings.rewards_payouts.rounds }} rounds ago.
The calculated rewards are then paid out on a block-by-block basis starting at the second block of the round. For every block, one collator will be chosen to receive their entire reward payout from the prior round, along with their delegators, until all rewards have been paid out for that round. For example, if there are {{ networks.moonriver.staking.max_candidates }} collators who produced blocks in the prior round, all of the collators and their delegators will be paid by block {{ networks.moonriver.staking.paid_out_block }} of the new round.
You can choose to auto-compound your delegation rewards so you no longer have to manually delegate rewards. If you choose to set up auto-compounding, you can specify the percentage of rewards to be auto-compounded. These rewards will then be automatically added to your delegation.
### Annual Inflation {: #annual-inflation}
The distribution of the annual inflation goes as follows:
=== "Moonbeam"
| Variable | Value |
|:-----------------------------------------:|:-------------------------------------------------------------------------------------:|
| Annual inflation | {{ networks.moonbeam.inflation.total_annual_inflation }}% |
| Rewards pool for collators and delegators | {{ networks.moonbeam.inflation.delegator_reward_inflation }}% of the annual inflation |
| Collator commission | {{ networks.moonbeam.inflation.collator_reward_inflation }}% of the annual inflation |
| Parachain bond reserve | {{ networks.moonbeam.inflation.parachain_bond_inflation }}% of the annual inflation |
=== "Moonriver"
| Variable | Value |
|:-----------------------------------------:|:--------------------------------------------------------------------------------------:|
| Annual inflation | {{ networks.moonriver.inflation.total_annual_inflation }}% |
| Rewards pool for collators and delegators | {{ networks.moonriver.inflation.delegator_reward_inflation }}% of the annual inflation |
| Collator commission | {{ networks.moonriver.inflation.collator_reward_inflation }}% of the annual inflation |
| Parachain bond reserve | {{ networks.moonriver.inflation.parachain_bond_inflation }}% of the annual inflation |
=== "Moonbase Alpha"
| Variable | Value |
|:-----------------------------------------:|:-------------------------------------------------------------------------------------:|
| Annual inflation | {{ networks.moonbase.inflation.total_annual_inflation }}% |
| Rewards pool for collators and delegators | {{ networks.moonbase.inflation.delegator_reward_inflation }}% of the annual inflation |
| Collator commission | {{ networks.moonbase.inflation.collator_reward_inflation }}% of the annual inflation |
| Parachain bond reserve | {{ networks.moonbase.inflation.parachain_bond_inflation }}% of the annual inflation |
From the rewards pool, collators get the rewards corresponding to their stake in the network. The rest are distributed among delegators by stake.
### Calculating Rewards {: #calculating-rewards }
Mathematically speaking, for collators, the reward distribution per block proposed and finalized would look like this:

Where `amount_due` is the corresponding inflation being distributed in a specific block, the `stake` corresponds to the number of tokens bonded by the collator in respect to the total stake of that collator (accounting delegations).
For each delegator, the reward distribution (per block proposed and finalized by the delegated collator) would look like this:

Where `amount_due` is the corresponding inflation being distributed in a specific block, the `stake` corresponds to the amount of tokens bonded by each delegator in respect to the total stake of that collator.
## Risks {: #risks }
*Holders of MOVR/GLMR tokens should perform careful due diligence on collators before delegating. Being listed as a collator is not an endorsement or recommendation from the Moonbeam Network, the Moonriver Network, or Moonbeam Foundation. Neither the Moonbeam Network, Moonriver Network, nor Moonbeam Foundation has vetted the list collators and assumes no responsibility with regard to the selection, performance, security, accuracy, or use of any third-party offerings. You alone are responsible for doing your own diligence to understand the applicable fees and all risks present, including actively monitoring the activity of your collators.*
*You agree and understand that neither the Moonbeam Network, the Moonriver Network, nor Moonbeam Foundation guarantees that you will receive staking rewards and any applicable percentage provided (i) is an estimate only and not guaranteed, (ii) may change at any time and (iii) may be more or less than the actual staking rewards you receive. The Moonbeam Foundation makes no representations as to the monetary value of any rewards at any time.*
*Staking MOVR/GLMR tokens is not free of risk.*
*Staked MOVR/GLMR tokens are locked up, and retrieving them requires a {{ networks.moonriver.delegator_timings.del_bond_less.days }} day/{{ networks.moonbeam.delegator_timings.del_bond_less.days }} day waiting period .*
*Additionally, if a collator fails to perform required functions or acts in bad faith, a portion of their total stake can be slashed (i.e. destroyed). This includes the stake of their delegators. If a collators behaves suspiciously or is too often offline, delegators can choose to unbond from them or switch to another collator. Delegators can also mitigate risk by electing to distribute their stake across multiple collators.*
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/features/treasury/
--- BEGIN CONTENT ---
---
title: Treasury
description: Moonbeam has an on-chain Treasury controlled by Treasury Council members, enabling stakeholders to submit proposals to further the network.
categories: Basics
---
# Treasury on Moonbeam
## Introduction {: #introduction }
The Moonbeam Treasury is an on-chain collection of funds launched at the network's genesis. Initially pre-funded with 0.5% of the token supply, the Treasury continues to accumulate GLMR as {{ networks.moonbeam.inflation.parachain_bond_treasury }}% of the parachain bond reserve inflation goes to the Treasury. For more information about Moonbeam inflation figures, see [GLMR Tokenomics](https://moonbeam.foundation/glimmer-token-tokenomics/){target=\_blank}.
The Moonbeam Treasury funds initiatives that support and grow the network. Stakeholders can propose spending requests for Treasury Council review, focusing on efforts like integrations, collaborations, community events, and outreach. Treasury spend proposers must submit their proposals to the [Moonbeam Forum](https://forum.moonbeam.network/c/governance/treasury-proposals/8){target=\_blank}. For submission details, see [How to Propose a Treasury Spend](/tokens/governance/treasury-spend/){target=\_blank}.
The [Treasury Council](https://forum.moonbeam.network/g/TreasuryCouncil){target=\_blank} oversees the spending of the Moonbeam Treasury and votes on funding proposals. It comprises two members from the Moonbeam Foundation and three external community members. The three external members are elected to terms of {{ networks.moonbeam.treasury.months_elected }} months. The same Treasury Council oversees Treasury requests for both Moonbeam and Moonriver. The Council meets monthly to review proposals submitted on the [Moonbeam Forum](https://forum.moonbeam.network/c/governance/treasury-proposals/8){target=\_blank}. Once a proposal is agreed upon, the Council members must complete the on-chain approval process.
## General Definitions {: #general-definitions }
Some important terminology to understand regarding treasuries:
- **Treasury Council** — a group of Moonbeam Foundation representatives and external community members. The Council reviews funding proposals, ensures alignment with the community, and ultimately authorizes Treasury spending
- **Proposal** — a plan or suggestion submitted by stakeholders to further the network to be approved by the Treasury Council
## Treasury Addresses {: #treasury-addresses }
The Treasury address for each respective network can be found below:
=== "Moonbeam"
[0x6d6F646c70632f74727372790000000000000000](https://moonbase.subscan.io/account/0x6d6F646c70632f74727372790000000000000000){target=_blank}
=== "Moonriver"
[0x6d6f646C70792f74727372790000000000000000](https://moonriver.subscan.io/account/0x6d6f646C70792f74727372790000000000000000){target=_blank}
=== "Moonbase Alpha"
[0x6d6F646c70632f74727372790000000000000000](https://moonbase.subscan.io/account/0x6d6F646c70632f74727372790000000000000000){target=_blank}
## Roadmap of a Treasury Proposal {: #roadmap-of-a-treasury-proposal }
The happy path of a Treasury spend request is as follows:
1. **Proposal submission** - the user submits a proposal to the [Moonbeam Forum](https://forum.moonbeam.network/c/governance/treasury-proposals/8){target=\_blank}
2. **Forum discussion** - the proposal is discussed by the community on the Forum. The ultimate Aye/Nay decision is determined by the Treasury council
3. **Treasury approval and action** - if the Treasury Council agrees, it authorizes the Treasury spending and moves the process forward
## Treasury Council Voting Process {: #treasury-council-voting-process }
A member of the Treasury Council will submit a `treasury.spend` call. This call requires specifying the amount, the asset type, and the beneficiary account to receive the funds. The Treasury supports spending various token types beyond GLMR, including native USDT/USDC. Once this extrinsic is submitted, a new Treasury Council collective proposal will be created and made available for council members to vote on. Once approved through the Treasury Council's internal voting process, the funds will be released automatically to the beneficiary account through the `treasury.payout` extrinsic.
!!! note
There is no on-chain action for the proposer or beneficiary of the Treasury spend request.
All Treasury spend actions will be completed by members of the Treasury Council.
Note that this process has changed significantly from prior Treasury processes, where tokenholders could submit Treasury proposals with bonds attached. Now, no on-chain action is necessary to submit a Treasury proposal. Rather, all that is needed is to raise a Treasury Council request on the [Moonbeam Forum](https://forum.moonbeam.network/c/governance/treasury-proposals/8){target=\_blank} and the Treasury Council will take care of the on-chain components.
For more information, see [How to Propose a Treasury Spend](/tokens/governance/treasury-spend/#next-steps){target=\_blank}
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/features/xchain-plans/
--- BEGIN CONTENT ---
---
title: Cross-Chain Communication
description: This guide covers the ways you can build cross-chain dApps with Moonbeam, including via XCM, cross consensus messaging, and GMP, general message passing.
categories: Basics, XCM
---
# Cross-Chain Communication Methods
Moonbeam makes it easy for developers to build smart contracts that connect across chains, both within the Polkadot ecosystem and outside the Polkadot ecosystem. This page will provide an overview of the underlying protocols that enable cross-chain communication and how you can leverage them to build connected contracts. For step-by-step guides of how to put these principles into practice, be sure to check out the [interoperability tutorials](/tutorials/interoperability/){target=\_blank}.
Two key terms that will come up frequently in this guide are XCM and GMP. [XCM](/builders/interoperability/xcm/){target=\_blank} refers to cross-consensus messaging, and it's Polkadot's native interoperability language that facilitates communication between Polkadot blockchains. You can read more about the [standardized XCM message format](https://docs.polkadot.com/develop/interoperability/intro-to-xcm/){target=\_blank} and [How to Get Started Building with XCM](/builders/interoperability/xcm/){target=\_blank}.
[GMP](https://moonbeam.network/news/seamless-blockchain-interoperability-the-power-of-general-message-passing-gmp){target=\_blank}, or general message passing, refers to the sending and receiving of messages within decentralized blockchain networks. While XCM is a type of general message passing, GMP colloquially refers to cross-chain communication between Moonbeam and blockchains outside of Polkadot. Similarly, in this guide, XCM refers to cross-chain messaging within Polkadot, and GMP refers to cross-chain messaging between Moonbeam and other ecosystems outside of Polkadot.
## Quick Reference {: #quick-reference }
=== "Comparison of XCM vs GMP"
| Specification | XCM | GMP |
|:---------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
| **Scope** | Polkadot and its connected parachains | Any blockchain supported by a GMP provider |
| **Provider** | Polkadot | [Axelar](/builders/interoperability/protocols/axelar/){target=\_blank}, [Wormhole](/builders/interoperability/protocols/wormhole/){target=\_blank}, [LayerZero](/builders/interoperability/protocols/layerzero/){target=\_blank}, [Hyperlane](/builders/interoperability/protocols/hyperlane/){target=\_blank}, etc. |
| **Implementation** | [XCM Virtual Machine](https://wiki.polkadot.com/learn/learn-xcvm/){target=\_blank} | Smart contracts |
| **Security** | Polkadot's shared security | Proprietary consensus determined by GMP provider |
| **Fees** | [Purchased with `BuyExecution` XCM instruction with supported asset](/builders/interoperability/xcm/core-concepts/weights-fees/){target=\_blank} | User sends value with transaction to pay for gas on the destination chain |
| **Adding New Chains** | Requires creation of XCM channels by both connected chains | Requires GMP provider to add support |
## XCM Transport Methods {: #xcm-transport-methods }
XCMP is the protocol that carries messages conforming to the XCM standard. The difference between the two is easy to remember with the added letter "P" for protocol. While XCM is the language that defines the format of the message to send, XCMP can be thought of as the pipes that enable the delivery of said messages.
XCMP is comprised of channels that enable communication between connected blockchains. When a parachain launches on Polkadot, two XCM channels are established automatically to allow for communication between the Polkadot relay chain and the parachain itself. XCM channels are omnidirectional, so two channels must be established for bidirectional communication.
Polkadot parachains can optionally choose to establish additional XCM channels with other parachains. Establishing XCM channels with other chains is a double opt-in process, so the receiving chain must also agree to have the channel established. Establishing XCM channels with another parachain allows for the exchange of XCM messages, enabling the flow of cross-chain assets and remote contract calls, to name a few examples.
There are several different subcategories of XCM transport methods, including:
### VMP {: #vmp }
VMP, or [Vertical Message Passing](https://wiki.polkadot.com/learn/learn-xcm-transport/#vmp-vertical-message-passing){target=\_blank}, refers to message passing between the relay chain and a parachain. Given that XCM channels are one-way, there are two types of message passing that comprise VMP, namely:
- **UMP** - Upward Message Passing refers to message passing from a parachain to the relay chain
- **DMP** - Downward Message Passing refers to message passing from the relay chain to a parachain
### HRMP {: #HRMP }
[Horizontal Relay-routed Message Passing](https://wiki.polkadot.com/learn/learn-xcm-transport/#hrmp-xcmp-lite){target=\_blank} (HRMP) is a temporary protocol that is currently being used while XCMP (Cross-Chain Message Passing) is still under development. HRMP serves as a placeholder and provides the same functionality and interface as XCMP. However, HRMP is more resource-intensive because it stores all messages within the Relay Chain's storage.
When opening XCM channels with other parachains today, those channels are using HRMP in place of the aforementioned XCMP. Once the implementation of XCMP is complete, the plan is to phase out HRMP and replace it with XCMP gradually. For more information about each one, be sure to check out [Polkadot's Guide to XCM Transport](https://wiki.polkadot.com/learn/learn-xcm-transport/){target=\_blank}.
## General Message Passing {: #general-message-passing }
As you know, GMP colloquially refers to cross-chain communication between Moonbeam and other blockchains outside of Polkadot. General message passing is enabled by cross-chain protocols that specialize in cross-chain communication. Each GMP provider takes a slightly different approach, but conceptually, they are quite similar. There are different contracts and functions for each provider, but each GMP provider has the same end goal: to provide secure and reliable cross-chain communication.
### Happy Path of a Cross-Chain Message {: #happy-path-of-a-cross-chain-message }
At a high level, the happy path of a message sent via GMP is as follows. A user or developer will call a contract specific to the GMP protocol, sometimes referred to as a mailbox contract or a gateway contract. This call typically includes parameters like the destination chain, the destination contract address, and includes sufficient value to pay for the transaction on the destination chain. A GMP provider listens for specific events on the origin blockchain pertaining to their gateway or mailbox contracts that indicate that a user wants to send a cross-chain message using their protocol. The GMP provider will validate certain parameters, including whether or not sufficient value was provided to pay for gas on the destination chain. In fact, the GMP provider may have a decentralized network of many nodes checking the authenticity of the message and verifying parameters. The GMP provider will not validate the integrity of the contract call to be delivered on the destination chain. E.g., the GMP provider will happily deliver a valid, paid-for message that contains a smart contract call that reverts on arrival. Finally, if everything checks out according to the consensus mechanism of the GMP provider, the message will be delivered to the destination chain, triggering the respective contract call at the destination.

### GMP Providers Integrated with Moonbeam {: #gmp-providers-integrated-with-moonbeam }
A large number of GMP providers have integrated with Moonbeam, which is beneficial for several reasons. For one, it enables you to work with whichever GMP provider you prefer. Second, it means that Moonbeam is connected to a rapidly growing number of chains. Whenever a GMP provider integrated with Moonbeam adds support for another chain, Moonbeam is automatically now connected with that chain. GMP providers are constantly adding support for new chains, and it's exciting to see those new integrations benefit the Moonbeam community. Additionally, having a variety of GMP providers allows for redundancy and backup. GMP providers have occasional maintenance windows or downtime; thus, it may make sense to add support for multiple GMP providers to ensure consistent uptime.
A significant number of GMP providers have integrated with Moonbeam, offering multiple benefits. Firstly, this integration allows users the flexibility to choose their preferred GMP provider. Secondly, Moonbeam's connectivity is enhanced as it automatically links with any new chains that its GMP providers support. Given that GMP providers frequently expand their support to new chains, the continuous roll out of new chains is a promising ongoing benefit for the Moonbeam community. Additionally, the diversity of GMP providers ensures better reliability and backup options. Since GMP providers can occasionally experience downtime or scheduled maintenance, the ability to integrate with multiple GMP providers is an important benefit.
The following GMP providers have integrated with Moonbeam:
- [Axelar](/builders/interoperability/protocols/axelar/){target=\_blank}
- [Hyperlane](/builders/interoperability/protocols/hyperlane/){target=\_blank}
- [LayerZero](/builders/interoperability/protocols/layerzero/){target=\_blank}
- [Wormhole](/builders/interoperability/protocols/wormhole/){target=\_blank}
## Implementing Both XCM and GMP {: #implementing-both-xcm-and-gmp }
Building with XCM or GMP does not preclude building with the other. As they suit different use cases, a team may seek to utilize XCM to handle interoperability needs within Polkadot, and GMP to deliver cross-chain messages to and from blockchains outside of Polkadot. As an example, several DEXes on Moonbeam support the trading of tokens migrated to Moonbeam via XCM, such as xcDOT, and assets bridged from ecosystems outside of Polkadot, such as USDC via Wormhole.
### Moonbeam Routed Liquidity {: #moonbeam-routed-liquidity }
[Moonbeam Routed Liquidity](/builders/interoperability/mrl/) (MRL) enables seamless liquidity between external blockchains connected to Moonbeam via Wormhole to Polkadot parachains connected to Moonbeam via XCM. This combination of GMP and XCM means that any ERC-20 token on a chain that Wormhole has integrated with can be routed through Moonbeam to a destination parachain (and back). A diagram of the happy path of a token transfer to a parachain via MRL is shown below, and you can find more information at the [MRL docs](/builders/interoperability/mrl/).

The information presented herein has been provided by third parties and is made available solely for general information purposes. Moonbeam does not endorse any project listed and described on the Moonbeam Doc Website (https://docs.moonbeam.network/). Moonbeam Foundation does not warrant the accuracy, completeness or usefulness of this information. Any reliance you place on such information is strictly at your own risk. Moonbeam Foundation disclaims all liability and responsibility arising from any reliance placed on this information by you or by anyone who may be informed of any of its contents. All statements and/or opinions expressed in these materials are solely the responsibility of the person or entity providing those materials and do not necessarily represent the opinion of Moonbeam Foundation. The information should not be construed as professional or financial advice of any kind. Advice from a suitably qualified professional should always be sought in relation to any particular matter or circumstance. The information herein may link to or integrate with other websites operated or content provided by third parties, and such other websites may link to this website. Moonbeam Foundation has no control over any such other websites or their content and will have no liability arising out of or related to such websites or their content. The existence of any such link does not constitute an endorsement of such websites, the content of the websites, or the operators of the websites. These links are being provided to you only as a convenience and you release and hold Moonbeam Foundation harmless from any and all liability arising from your use of this information or the information provided by any third-party website or service.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/platform/code/
--- BEGIN CONTENT ---
---
title: Moonbeam Source Code
description: Moonbeam is an open source project in the Polkadot ecosystem, with publicly available and auditable source code.
categories: Basics
---
# Moonbeam Source Code
Moonbeam is an open source project. The main Moonbeam repo can be found here:
[:fontawesome-brands-github: https://github.com/moonbeam-foundation/moonbeam](https://github.com/moonbeam-foundation/moonbeam){target=\_blank}
Moonbeam is implemented using the Substrate framework. The source code for Substrate can be found here:
[:fontawesome-brands-github: https://github.com/paritytech/substrate](https://github.com/paritytech/polkadot-sdk/tree/master/substrate){target=\_blank}
We also work on Ethereum compatibility features along with engineers from Parity as part of the Frontier project. Source code for Frontier can be found here:
[:fontawesome-brands-github: https://github.com/polkadot-evm/frontier](https://github.com/polkadot-evm/frontier){target=\_blank}
If you are interested in contributing code to Moonbeam, please raise an issue or PR on the [Moonbeam GitHub repository](https://github.com/moonbeam-foundation/moonbeam){target=\_blank}
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/platform/links/
--- BEGIN CONTENT ---
---
title: Important Moonbeam Related Links
description: If you're new to Moonbeam or the Polkadot network, here are some important links to review, including compatible Ethereum tools.
categories: Basics
---
# Links
- **[Polkadot Docs](https://docs.polkadot.com/){target=\_blank}** - starting point for learning about the [Polkadot SDK](https://docs.polkadot.com/develop/parachains/intro-polkadot-sdk/){target=\_blank}, a Rust-based framework for developing blockchains. Moonbeam is developed using Substrate and uses many of the modules that come with it
- **[Polkadot.com](https://polkadot.com){target=\_blank}** - learn about Polkadot, including the vision behind the network and how the system works, i.e., staking, governance, etc.
- **[Polkadot-JS Apps](https://polkadot.js.org/apps){target=\_blank}** - a web-based interface for interacting with Substrate based nodes, including Moonbeam
- **[Solidity Docs](https://solidity.readthedocs.io){target=\_blank}** - Solidity is the main smart contract programming language supported by Ethereum and Moonbeam. The Solidity docs site is very comprehensive
- **[Remix](https://remix.ethereum.org){target=\_blank}** - web-based IDE for Solidity smart contract development that is compatible with Moonbeam
- **[Hardhat](https://hardhat.org){target=\_blank}** - development tools for Solidity, including debugging, testing, and automated deployment that is compatible with Moonbeam
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/platform/networks/moonbase/
--- BEGIN CONTENT ---
---
title: Moonbase Alpha TestNet Overview
description: An overview of the current configuration of the Moonbeam TestNet, Moonbase Alpha, and information on how to start building on it using Solidity.
categories: Basics
---
# The Moonbase Alpha TestNet
## Goal {: #goal }
The first Moonbeam TestNet, named Moonbase Alpha, aims to provide developers with a place to start experimenting and building on Moonbeam in a shared environment. Since Moonbeam is deployed as a parachain on Kusama and Polkadot, the goal of the TestNet is to reflect the production configurations. For this reason, it was decided that it needed to be a parachain-based configuration rather than a Substrate development setup.
In order to collect as much feedback as possible and provide fast issue resolution, please join the [Moonbeam Discord](https://discord.com/invite/PfpUATX){target=\_blank}.
## Initial Configuration {: #initial-configuration }
Moonbase Alpha has the following configuration:
- Runs as a parachain connected to a relay chain
- Has an active set of {{ networks.moonbase.staking.max_candidates }} collator nodes run by the community
- The relay chain hosts validators to finalize relay chain blocks. One of them is selected to finalize each block collated by Moonbeam's collators. This setup provides room to expand to a two-parachain configuration in the future
- Has infrastructure providers that provide [API endpoints](/builders/get-started/endpoints/){target=\_blank} to connect to the network. Projects can also [run their own node](/node-operators/networks/run-a-node/){target=\_blank} to have access to their own private endpoints

Some important variables/configurations to note include:
=== "General"
| Variable | Value |
|:---------------------:|:------------------------------------------:|
| Minimum gas price | {{ networks.moonbase.min_gas_price }} Gwei |
| Target block time | {{ networks.moonbase.block_time }} seconds |
| Block gas limit | {{ networks.moonbase.gas_block }} |
| Transaction gas limit | {{ networks.moonbase.gas_tx }} |
=== "Staking"
| Variable | Value |
|:---------------------------------:|:-------------------------------------------------------------------------------------------------------------------------------------------:|
| Minimum delegation stake | {{ networks.moonbase.staking.min_del_stake }} DEV |
| Maximum delegators per candidates | {{ networks.moonbase.staking.max_del_per_can }} |
| Maximum delegations per account | {{ networks.moonbase.staking.max_del_per_del }} |
| Round | {{ networks.moonbase.staking.round_blocks }} blocks ({{ networks.moonbase.staking.round_hours }} hour) |
| Bond duration | Delegations take effect in the next round; funds are withdrawn immediately |
| Unbond duration | {{ networks.moonbase.delegator_timings.del_bond_less.rounds }} rounds ({{ networks.moonbase.delegator_timings.del_bond_less.hours }} hours) |
!!! note
As of runtime 3000, [asynchronous backing](https://wiki.polkadot.com/learn/learn-async-backing/#asynchronous-backing){target=\_blank} has been enabled on all Moonbeam networks. As a result, the target block time was reduced from 12 seconds to 6 seconds, which may break some timing-based assumptions.
Additionally, as of runtime 2900, the block and transaction gas limits increased by 4x on Moonbase Alpha.
## Network Endpoints {: #network-endpoints }
Moonbase Alpha has two types of endpoints available for users to connect to: one for HTTPS and one for WSS.
If you're looking for your own endpoints suitable for production use, you can check out the [Endpoint Providers](/builders/get-started/endpoints/#endpoint-providers){target=\_blank} section of our documentation. Otherwise, to get started quickly you can use one of the following public HTTPS or WSS endpoints.
=== "HTTPS"
| Provider | RPC URL | Limits |
|:-------------------:|:------------------------------------------------------------------:|:-----------:|
| Dwellir |
| 200 req/sec |
#### Relay Chain {: #relay-chain }
To connect to the Moonbase Alpha relay chain, you can use the following WS Endpoint:
| Provider | RPC URL |
|:--------:|:----------------------------------------------------------:|
| OpsLayer |
```wss://relay.api.moonbase.moonbeam.network```
|
## Quick Start {: #quick-start }
For the [Web3.js library](/builders/ethereum/libraries/web3js/){target=\_blank}, you can create a local Web3 instance and set the provider to connect to Moonbase Alpha (both HTTP and WS are supported):
```js
const { Web3 } = require('web3'); // Load Web3 library
.
.
.
// Create local Web3 instance - set Moonbase Alpha as provider
const web3 = new Web3('https://rpc.api.moonbase.moonbeam.network');
```
For the [Ethers.js library](/builders/ethereum/libraries/ethersjs/){target=\_blank}, define the provider by using `ethers.JsonRpcProvider(providerURL, {object})` and setting the provider URL to Moonbase Alpha:
```js
const ethers = require('ethers'); // Load Ethers library
const providerURL = 'https://rpc.api.moonbase.moonbeam.network';
// Define provider
const provider = new ethers.JsonRpcProvider(providerURL, {
chainId: 1287,
name: 'moonbase-alphanet'
});
```
Any Ethereum wallet should be able to generate a valid address for Moonbeam (for example, [MetaMask](https://metamask.io){target=\_blank}).
## Chain ID {: #chain-id }
Moonbase Alpha TestNet chain ID is: `1287`, which is `0x507` in hex.
## Alphanet Relay Chain {: #relay-chain }
The Alphanet relay chain is connected to Moonbase Alpha and is [Westend](https://polkadot.com/blog/westend-introducing-a-new-testnet-for-polkadot-and-kusama){target=\_blank}-based but unique to the Moonbeam ecosystem. It resembles how you would interact with Kusama or Polkadot. The native tokens of the Alphanet relay chain are UNIT tokens, which are for testing purposes only and have no real value.
## Telemetry {: #telemetry }
You can see current Moonbase Alpha telemetry information by visiting [Polkadot's Telemetry dashboard](https://telemetry.polkadot.io/#list/0x91bc6e169807aaa54802737e1c504b2577d4fafedd5a02c10293b1cd60e39527){target=\_blank}.
## Tokens {: #tokens }
Tokens on Moonbase Alpha, named DEV, will be issued on demand. **DEV tokens hold no value and can be freely acquired**.
You can enter your address to automatically request DEV tokens from the [Moonbase Alpha Faucet](https://faucet.moonbeam.network){target=\_blank} website. The faucet dispenses {{ networks.moonbase.website_faucet_amount }} every 24 hours.
For token requests of more than the limited amount allowed by the faucet, contact a moderator directly via the [Moonbeam Discord server](https://discord.com/invite/PfpUATX){target=\_blank}. We are happy to provide the tokens needed to test your applications.
## Proof of Stake {: #proof-of-stake }
The Moonbase Alpha TestNet is a fully decentralized Delegated Proof of Stake network where users of the network can delegate collator candidates to produce blocks and "earn rewards" for testing purposes. Please note, that the Moonbase Alpha DEV tokens have no real value. The number of candidates in the active set will be subject to governance. The active set will consist of the top candidates by stake, including delegations.
## Limitations {: #limitations }
This is the first TestNet for Moonbeam, so there are some limitations.
Some [precompiles](https://www.evm.codes/precompiled){target=\_blank} are yet to be included. You can check out the list of supported precompiles on the [Canonical Contract page](/builders/ethereum/precompiles/){target=\_blank}. However, all built-in functions are available.
Since the release of Moonbase Alpha v6, the maximum gas limit per block has been set to {{ networks.moonbase.gas_block }}, with a maximum gas limit per transaction of {{ networks.moonbase.gas_tx }}.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/platform/networks/moonbeam/
--- BEGIN CONTENT ---
---
title: Moonbeam Network Overview
description: An overview of the current configuration of the Moonbeam deployment on Polkadot, Moonbeam, and information on how to start building on it using Solidity.
categories: Basics
---
# Moonbeam
## Goal {: #goal }
Moonbeam was onboarded as a parachain to Polkadot on December 17th 2021. Moonbeam is the most Ethereum compatible smart-contract parachain in the Polkadot ecosystem. It allows developers to port their projects with minimal to no code changes, enabling them to tap into the Polkadot ecosystem and all its assets.
In order to collect as much feedback as possible and provide fast issue resolution, you can check out the dedicated [Moonbeam Network section on Discord](https://discord.com/invite/PfpUATX){target=\_blank}.
## Initial Configurations {: #initial-configurations }
Currently, Moonbeam has the following configurations:
- Runs as a parachain connected to the Polkadot relay chain
- Has an active set of {{ networks.moonbeam.staking.max_candidates }} collators
- Has infrastructure providers that provide [API endpoints](/builders/get-started/endpoints/){target=\_blank} to connect to the network. Projects can also [run their own node](/node-operators/networks/run-a-node/){target=\_blank} to have access to their own private endpoints

Some important variables/configurations to note include (still subject to change):
=== "General"
| Variable | Value |
|:---------------------:|:-----------------------------------------------------------------------:|
| Minimum gas price | {{ networks.moonbeam.min_gas_price }} Gwei* |
| Target block time | {{ networks.moonbeam.block_time }} seconds |
| Block gas limit | {{ networks.moonbeam.gas_block }} |
| Transaction gas limit | {{ networks.moonbeam.gas_tx }} |
=== "Staking"
| Variable | Value |
|:---------------------------------:|:-------------------------------------------------------------------------------------------------------:|
| Minimum delegation stake | {{ networks.moonbeam.staking.min_del_stake }} GLMR |
| Maximum delegators per candidates | {{ networks.moonbeam.staking.max_del_per_can }} |
| Maximum delegations per account | {{ networks.moonbeam.staking.max_del_per_del }} |
| Round | {{ networks.moonbeam.staking.round_blocks }} blocks ({{ networks.moonbeam.staking.round_hours }} hours) |
| Bond duration | delegation takes effect in the next round (funds are withdrawn immediately) |
| Unbond duration | {{ networks.moonbeam.delegator_timings.del_bond_less.rounds }} rounds |
_*Read more about [token denominations](#token-denominations)_
## Network Endpoints {: #network-endpoints }
Moonbeam has two types of endpoints available for users to connect to: one for HTTPS and one for WSS.
If you're looking for your own endpoints suitable for production use, you can check out the [Endpoint Providers](/builders/get-started/endpoints/#endpoint-providers){target=\_blank} section of our documentation. Otherwise, to get started quickly you can use one of the following public HTTPS or WSS endpoints:
=== "HTTPS"
| Provider | RPC URL | Limits |
|:-----------:|:------------------------------------------------------------------:|:-----------:|
| Dwellir |
| 10k req/day |
## Quick Start {: #quick-start }
Before getting started, make sure you've retrieved your own endpoint and API key from one of the custom [Endpoint Providers](/builders/get-started/endpoints/){target=\_blank}. Then for the [Web3.js library](/builders/ethereum/libraries/web3js/){target=\_blank}, you can create a local Web3 instance and set the provider to connect to Moonbeam (both HTTP and WS are supported):
```js
const { Web3 } = require('web3'); // Load Web3 library
.
.
.
// Create local Web3 instance - set Moonbeam as provider
const web3 = new Web3('INSERT_RPC_API_ENDPOINT'); // Insert your RPC URL here
```
For the [Ethers.js library](/builders/ethereum/libraries/ethersjs/){target=\_blank}, define the provider by using `ethers.JsonRpcProvider(providerURL, {object})` and setting the provider URL to Moonbeam:
```js
const ethers = require('ethers'); // Load Ethers library
const providerURL = 'INSERT_RPC_API_ENDPOINT'; // Insert your RPC URL here
// Define provider
const provider = new ethers.JsonRpcProvider(providerURL, {
chainId: 1284,
name: 'moonbeam'
});
```
Any Ethereum wallet should be able to generate a valid address for Moonbeam (for example, [MetaMask](https://metamask.io){target=\_blank}).
## Chain ID {: #chain-id }
Moonbeam chain ID is: `1284`, or `0x504` in hex.
## Telemetry {: #telemetry }
You can see current Moonbeam telemetry information by visiting [Polkadot's Telemetry dashboard](https://telemetry.polkadot.io/#list/0xfe58ea77779b7abda7da4ec526d14db9b1e9cd40a217c34892af80a9b332b76d){target=\_blank}.
## Tokens {: #tokens }
The tokens on Moonbeam are called Glimmer (GLMR). Check out the Moonbeam Foundation site for more information on the [Glimmer](https://moonbeam.foundation/glimmer-token-tokenomics){target=\_blank} token.
### Token Denominations {: #token-denominations }
The smallest unit of Glimmer (GMLR), similarly to Ethereum, is a Wei. It takes 10^18 Wei to make one Glimmer. The denominations are as follows:
| Unit | Glimmer (GLMR) | Wei |
|:---------:|:--------------------:|:-----------------------------:|
| Wei | 0.000000000000000001 | 1 |
| Kilowei | 0.000000000000001 | 1,000 |
| Megawei | 0.000000000001 | 1,000,000 |
| Gigawei | 0.000000001 | 1,000,000,000 |
| Microglmr | 0.000001 | 1,000,000,000,000 |
| Milliglmr | 0.001 | 1,000,000,000,000,000 |
| GLMR | 1 | 1,000,000,000,000,000,000 |
| Kiloglmr | 1,000 | 1,000,000,000,000,000,000,000 |
## Proof of Stake {: #proof-of-stake }
The Moonriver network is a fully decentralized Delegated Proof of Stake network where users of the network can delegate collator candidates to produce blocks and earn rewards. It uses the [Nimbus framework](/learn/features/consensus/){target=\_blank} framework for parachain consensus. The number of candidates in the active set will be subject to governance. The active set will consist of the top candidates by stake, including delegations.
## Limitations {: #limitations }
Some [precompiles](https://www.evm.codes/precompiled){target=\_blank} are yet to be included. You can check a list of supported precompiles on the [Solidity Precompiles page](/builders/ethereum/precompiles/overview/){target=\_blank}. However, all built-in functions are available.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/platform/networks/moonriver/
--- BEGIN CONTENT ---
---
title: Moonriver Overview
description: An overview of the current configuration of the Moonbeam deployment on Kusama, Moonriver, and information on how to start building on it using Solidity.
categories: Basics
---
# Moonriver
## Goal {: #goal }
In June 2021, Moonriver was first launched as a parachain on the Kusama network. Moonriver is a sister network of Moonbeam, and provides an environment to test new code under real economic conditions. Developers now have access to start building on an incentivized canary network connected to Kusama.
In order to collect as much feedback as possible and provide fast issue resolution, you can check out the dedicated [Moonriver section on Discord](https://discord.com/invite/5TaUvbRvgM){target=\_blank}.
## Initial Configurations {: #initial-configurations }
Currently, Moonriver has the following configurations:
- Runs as a parachain connected to the Kusama relay chain
- Has an active set of {{ networks.moonriver.staking.max_candidates }} collators
- Has infrastructure providers that provide [API endpoints](/builders/get-started/endpoints/){target=\_blank} to connect to the network. Projects can also [run their own node](/node-operators/networks/run-a-node/){target=\_blank} to have access to their own private endpoints

Some important variables/configurations to note include:
=== "General"
| Variable | Value |
|:---------------------:|:--------------------------------------------:|
| Minimum gas price | {{ networks.moonriver.min_gas_price }} Gwei* |
| Target block time | {{ networks.moonriver.block_time }} seconds |
| Block gas limit | {{ networks.moonriver.gas_block }} |
| Transaction gas limit | {{ networks.moonriver.gas_tx }} |
=== "Staking"
| Variable | Value |
|:---------------------------------:|:---------------------------------------------------------------------------------------------------------:|
| Minimum delegation stake | {{ networks.moonriver.staking.min_del_stake }} MOVR |
| Maximum delegators per candidates | {{ networks.moonriver.staking.max_del_per_can }} |
| Maximum delegations per account | {{ networks.moonriver.staking.max_del_per_del }} |
| Round | {{ networks.moonriver.staking.round_blocks }} blocks ({{ networks.moonriver.staking.round_hours }} hours) |
| Bond duration | delegation takes effect in the next round (funds are withdrawn immediately) |
| Unbond duration | {{ networks.moonriver.delegator_timings.del_bond_less.rounds }} rounds |
_*Read more about [token denominations](#token-denominations)_
!!! note
As of runtime 3000, [asynchronous backing](https://wiki.polkadot.com/learn/learn-async-backing/#asynchronous-backing){target=\_blank} has been enabled on all Moonbeam networks. As a result, the target block time was reduced from 12 seconds to 6 seconds, which may break some timing-based assumptions.
Additionally, the block and transaction gas limits increased by 4x on Moonriver.
## Network Endpoints {: #network-endpoints }
Moonriver has two types of endpoints available for users to connect to: one for HTTPS and one for WSS.
If you're looking for your own endpoints suitable for production use, you can check out the [Endpoint Providers](/builders/get-started/endpoints/#endpoint-providers){target=\_blank} section of our documentation. Otherwise, to get started quickly you can use one of the following public HTTPS or WSS endpoints:
=== "HTTPS"
| Provider | RPC URL | Limits |
|:-----------:|:-------------------------------------------------------------------:|:-----------:|
| Dwellir |
| 200 req/sec |
## Quick Start {: #quick-start }
Before getting started, make sure you've retrieved your own endpoint and API key from one of the custom [Endpoint Providers](/builders/get-started/endpoints/){target=\_blank}. Then for the [Web3.js library](/builders/ethereum/libraries/web3js/){target=\_blank}, you can create a local Web3 instance and set the provider to connect to Moonriver (both HTTP and WS are supported):
```js
const { Web3 } = require('web3'); // Load Web3 library
.
.
.
// Create local Web3 instance - set Moonriver as provider
const web3 = new Web3('INSERT_RPC_API_ENDPOINT'); // Insert your RPC URL here
```
For the [Ethers.js library](/builders/ethereum/libraries/ethersjs/){target=\_blank}, define the provider by using `ethers.JsonRpcProvider(providerURL, {object})` and setting the provider URL to Moonriver:
```js
const ethers = require('ethers'); // Load Ethers library
const providerURL = 'INSERT_RPC_API_ENDPOINT'; // Insert your RPC URL here
// Define provider
const provider = new ethers.JsonRpcProvider(providerURL, {
chainId: 1285,
name: 'moonriver'
});
```
Any Ethereum wallet should be able to generate a valid address for Moonbeam (for example, [MetaMask](https://metamask.io){target=\_blank}).
## Chain ID {: #chain-id }
Moonriver chain ID is: `1285`, or `0x505` in hex.
## Telemetry {: #telemetry }
You can see current Moonriver telemetry information by visiting [Polkadot's Telemetry dashboard](https://telemetry.polkadot.io/#list/0x401a1f9dca3da46f5c4091016c8a2f26dcea05865116b286f60f668207d1474b){target=\_blank}.
## Tokens {: #tokens }
The tokens on Moonriver will also be called Moonriver (MOVR). Check out the Moonbeam Foundation site for more information on the [Moonriver token](https://moonbeam.foundation/moonriver-token-tokenomics){target=\_blank}.
### Token Denominations {: #token-denominations }
The smallest unit of Moonriver, similarly to Ethereum, is a Wei. It takes 10^18 Wei to make one Moonriver. The denominations are as follows:
| Unit | Moonriver (MOVR) | Wei |
|:--------------:|:--------------------:|:-----------------------------:|
| Wei | 0.000000000000000001 | 1 |
| Kilowei | 0.000000000000001 | 1,000 |
| Megawei | 0.000000000001 | 1,000,000 |
| Gigawei | 0.000000001 | 1,000,000,000 |
| Micromoonriver | 0.000001 | 1,000,000,000,000 |
| Millimoonriver | 0.001 | 1,000,000,000,000,000 |
| Moonriver | 1 | 1,000,000,000,000,000,000 |
| Kilomoonriver | 1,000 | 1,000,000,000,000,000,000,000 |
## Proof of Stake {: #proof-of-stake }
The Moonriver network is a fully decentralized Delegated Proof of Stake network where users of the network can delegate collator candidates to produce blocks and earn rewards. It uses the [Nimbus framework](/learn/features/consensus/){target=\_blank} framework for parachain consensus. The number of candidates in the active set will be subject to governance. The active set will consist of the top candidates by stake, including delegations.
## Limitations {: #limitations }
Some [precompiles](https://www.evm.codes/precompiled){target=\_blank} are yet to be included. You can check a list of supported precompiles on the [Canonical Contract page](/builders/ethereum/precompiles/){target=\_blank}. However, all built-in functions are available.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/platform/networks/overview/
--- BEGIN CONTENT ---
---
title: Overview of Networks
description: An overview of all of the MainNet and TestNet deployments of Moonbeam, an Ethereum-compatible smart contract parachain on Polkadot and Kusama.
categories: Basics
---
# Networks
There are multiple long-lived Moonbeam-based networks. Most significantly, there is the Moonbeam deployment on Polkadot and Kusama.
An overview of our parachain deployments is as follows:
- Moonbeam: deployment on Polkadot (_December 2021_)
- Moonriver: deployment on Kusama (_June 2021_)
- Moonbase Alpha: Parachain TestNet for Moonbeam and Moonriver (_September 2020_)
This strategy allows us to de-risk software upgrades to Moonbeam on the Polkadot MainNet while still maintaining a reasonable update velocity.
## Moonbeam {: #moonbeam }
The Moonbeam production MainNet is a parachain on Polkadot and has been since December 17th, 2021. Moonbeam features the highest levels of security and availability. Code running on the MainNet has generally been vetted through one or more of the other networks listed above.
Moonbeam will offer parachain-related functionalities such as [XCMP](https://wiki.polkadot.com/learn/learn-xcm-transport/#xcmp-cross-chain-message-passing){target=\_blank} and [SPREE](https://wiki.polkadot.com/learn/learn-spree/){target=\_blank} as these features become available.
[Learn more about Moonbeam](/learn/platform/networks/moonbeam/).
## Moonriver {: #moonriver }
In advance of deploying to the Polkadot MainNet, [Moonbeam launched Moonriver](https://moonbeam.network/news/moonriver-won-a-parachain-slot-and-is-now-producing-blocks-on-the-kusama-network){target=\_blank} as a parachain on the Kusama network. The parachain functionality is live on Kusama.
Moonriver will offer parachain-related functionalities such as [XCMP](https://wiki.polkadot.com/learn/learn-xcm-transport/#xcmp-cross-chain-message-passing){target=\_blank} and [SPREE](https://wiki.polkadot.com/learn/learn-spree/){target=\_blank} as these features become available.
[Learn more about Moonriver](/learn/platform/networks/moonriver/).
## Moonbase Alpha {: #moonbase-alpha }
This TestNet is a network hosted by OpsLayer. It features a parachain/relay chain scheme. The goal is to allow developers to test the Ethereum compatibility features of Moonbeam in a shared parachain environment without needing to run their own nodes or network.
[Learn more about Moonbase Alpha](/learn/platform/networks/moonbase/).
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/platform/technology/
--- BEGIN CONTENT ---
---
title: Technology & Architecture
description: Moonbeam is built using Rust and Polkadot's Substrate framework, enabling rich tools for implementation while allowing for specialization and optimization.
categories: Basics
---
# Technology & Architecture
## The Moonbeam Development Stack {: #the-moonbeam-development-stack }
Moonbeam is a smart contract blockchain platform built in the Rust programming language using the Substrate framework. Substrate, developed by [Parity Technologies](https://www.parity.io/){target=_blank} (the original founding contributors of Polkadot), is an open-source, modular SDK for creating blockchains. Substrate allows developers to customize their blockchains while still benefiting from features such as forkless upgrades, shared security (when connected as a parachain to Polkadot or Kusama), and an extensive library of pre-built runtime modules known as pallets.
### Rust Programming Language {: #rust-programming-language }
Rust is a good language for implementing a blockchain. It is highly performant like C and C++ but has built-in memory safety features enforced at compile time, preventing many common bugs and security issues arising from C and C++ implementations.
### Substrate Framework {: #substrate-framework }
Substrate provides a rich set of tools for creating blockchains, including a runtime execution environment that enables a generic state transition function and a pluggable set of modules (pallets) that implement various blockchain subsystems. By using Substrate, Moonbeam can leverage several key features offered to parachains launched on the Polkadot relay chain, including:
- **Shared security** — Polkadot's validators secure all parachains
- **Cross-Consensus Messaging (XCM)** — native interoperability with other parachains
- **Flexible upgrades** — Substrate’s forkless upgrade mechanism
Pallets are at the heart of Substrate-based chains, providing specific functionality in modular form. Examples include:
- **Balances pallet** — manages account balances and transfers
- **Assets pallet** — handles the creation and management of on-chain fungible assets
- **Consensus pallets** — provide mechanisms like AURA or BABE for block production
- **Governance pallets** — facilitate on-chain governance
- **Frontier pallets** — the Ethereum compatibility layer pioneered by the Moonbeam team
- **Parachain Staking pallet** — enables Delegated Proof of Stake (DPoS)
In addition to these pallets provided by Polkadot's Substrate, developers can [create their own pallets](https://docs.polkadot.com/develop/parachains/customize-parachain/make-custom-pallet/){target=_blank} to add custom functionality. Moonbeam leverages multiple existing Substrate frame pallets as well as several custom pallets for features such as cross-chain token integration, the [Orbiter Program](/node-operators/networks/collators/orbiter/){target=_blank}, and more. You can find the Moonbeam runtime (built using Substrate) and related pallets in the [Moonbeam GitHub repository](https://github.com/moonbeam-foundation/moonbeam){target=_blank}.
Moonbeam also uses the Cumulus library to facilitate integration with the Polkadot relay chain.
### Frontier: Substrate's Ethereum Compatibility Layer {: #frontier }
[Frontier](https://polkadot-evm.github.io/frontier){target=\_blank} serves as Substrate's Ethereum compatibility layer, facilitating the seamless operation of standard Ethereum DApps on Substrate-based chains without requiring modifications. This compatibility is achieved by integrating specialized Substrate pallets into the Substrate runtime. These pallets include:
- **EVM pallet** — responsible for executing EVM operations
- **Ethereum pallet** — manages block data storage and offers RPC compatibility
- **Base Fee pallet and Dynamic Fee pallet** — provide EIP-1559 functionality (not used in Moonbeam)
Moonbeam uses the EVM and Ethereum pallets to achieve full Ethereum compatibility. Instead of the Base Fee or Dynamic Fee pallets, Moonbeam has its own [dynamic fee mechanism](https://forum.moonbeam.network/t/proposal-dynamic-fee-mechanism-for-moonbeam-and-moonriver/241){target=\_blank} for base fee calculations. Basing the EVM implementation on the Substrate EVM Pallet provides a Rust-based EVM engine and support from the Parity engineering team.
## Blockchain Runtime {: #blockchain-runtime }
The core Moonbeam runtime specifies the state transition function and behavior of the Moonbeam blockchain. The runtime is built using [FRAME](/learn/platform/glossary/#substrate-frame-pallets){target=\_blank}, compiled to a [WebAssembly (Wasm)](/learn/platform/glossary/#webassemblywasm){target=\_blank} binary as well as a native binary. These compiled versions are executed in the Polkadot relay chain and Moonbeam node environments.
!!! note
Substrate FRAME pallets are a collection of Rust-based modules that provide the functionality required when building a blockchain. WebAssembly is an open standard that defines a portable binary code format. Different programming languages, compilers, and browsers support it. Find more definitions [in our glossary](/learn/platform/glossary/){target=\_blank}.
Some of the key Substrate FRAME pallets used in the Moonbeam runtime include:
- **Balances** — support for accounts, balances, and transfers
- **EVM** — a full Rust-based EVM implementation based on SputnikVM (part of Frontier)
- **Ethereum** — provides emulation of Ethereum block processing for the EVM (part of Frontier)
- **Executive** — orchestration layer that dispatches calls to other runtime modules
- **Identity** — support for setting on-chain identities for account addresses
- **System** — provides low-level types, storage, and blockchain functions
- **Treasury** — on-chain treasury that can be used to fund public goods such as a parachain slot
In addition to these Substrate FRAME Pallets, Moonbeam implements custom pallets to achieve additional functionality, such as:
- **Parachain Staking** — enables a Delegated Proof of Stake (DPoS) system
- **Moonbeam Orbiters** — supports the [Orbiter Program](/node-operators/networks/collators/orbiter/){target=\_blank}, which diversifies the collator pool
- **XCM Transactor** — simplifies remote cross-chain calls via [Cross-Consensus Messaging (XCM)](/builders/interoperability/xcm/overview/){target=\_blank}
- **Asset Manager** — registers XCM assets
### Forkless Upgrades {: #forkless-upgrades }
One of the best things about developing on Polkadot with Substrate is the ability to introduce [forkless upgrades](https://docs.polkadot.com/develop/parachains/maintenance/runtime-upgrades/){target=_blank} to blockchain runtimes. In traditional blockchain architectures, substantial changes to the blockchain's rules often require a hard fork, which can be disruptive and contentious.
Substrate takes a different approach by separating the blockchain's state (data) from its logic (rules). Logic lives in the runtime, which is itself stored on-chain. Whenever a new runtime is uploaded (via FRAME's `set_code` call) and approved through on-chain governance, all nodes automatically switch to the new runtime at a specified block. This process is seamless and does not split the network.
Moonbeam regularly uses forkless upgrades to add features or fixes without requiring node operators to upgrade their software manually. You can keep track of and discuss upcoming Moonbeam upgrades on the [Moonbeam forum](https://forum.moonbeam.network){target=_blank}.
## Ethereum Compatibility Architecture {: #ethereum-compatibility-architecture }
Smart contracts on Moonbeam can be implemented using Solidity, Vyper, and any other language that compiles smart contracts to EVM-compatible bytecode. Moonbeam aims to provide a low-friction and secure environment for the development, testing, and execution of smart contracts while remaining compatible with the existing Ethereum developer toolchain.
The execution behavior and semantics of Moonbeam-based smart contracts strive to be as close as possible to Ethereum Layer 1. Moonbeam is a single shard, so cross-contract calls have the same synchronous execution semantics as on Ethereum Layer 1.

A high-level interaction flow is shown above. A Web3 RPC call from a DApp or existing Ethereum developer tool, such as Hardhat, is received by a Moonbeam node. The node has both Web3 RPCs and Substrate RPCs available, meaning you can use Ethereum or Substrate tools when interacting with a Moonbeam node. Associated Substrate runtime functions handle these RPC calls. The Substrate runtime checks signatures and handles any extrinsics. Smart contract calls are ultimately passed to the EVM to execute the state transitions.
### Ethereum Pallet {: #ethereum-pallet}
The [Ethereum pallet](https://polkadot-evm.github.io/frontier/overview){target=\_blank} is responsible for handling blocks and transaction receipts and statuses. It enables sending and receiving Ethereum-formatted data to and from Moonbeam by storing an Ethereum-style block and its associated transaction hashes in the Substrate runtime.
When a user submits a raw Ethereum transaction, it converts into a Substrate transaction through the Ethereum pallet's `transact` extrinsic—using the Ethereum pallet as the sole executor of the EVM pallet forces all of the data to be stored and transacted in an Ethereum-compatible way, which is how explorers like [Moonscan](/builders/get-started/explorers/#moonscan){target=\_blank} (built by Etherscan) can index block data.
### EVM Pallet {: #evm-pallet }
The [EVM pallet](https://polkadot-evm.github.io/frontier/overview){target=\_blank} implements a sandboxed virtual stack machine and uses the [SputnikVM](https://github.com/rust-ethereum/evm){target=\_blank} as the underlying EVM engine. It executes Ethereum smart contract bytecode in a manner similar to Ethereum mainnet, including gas metering and state changes.
Moonbeam uses unified accounts, meaning an H160 (Ethereum-style) address is also a valid Substrate address, so you only need a single account to interact with the Substrate runtime and the EVM. Once a balance exists in the EVM, smart contracts can be created and interacted with through standard Ethereum RPC calls.
The EVM pallet should produce nearly identical execution results to Ethereum, such as gas cost and balance changes. However, there are some differences. Although the EVM pallet aims for near-identical behavior to Ethereum, some differences exist, for example, Moonbeam's [dynamic fee mechanism](https://forum.moonbeam.network/t/proposal-dynamic-fee-mechanism-for-moonbeam-and-moonriver/241){target=\_blank}. For more information, refer to the [Frontier EVM Pallet documentation](https://polkadot-evm.github.io/frontier/){target=\_blank}.
Moonbeam includes additional EVM precompiles for functionalities like cryptographic operations (ECRecover, SHA256, BLAKE2, BN128) and dispatching Substrate calls directly from within the EVM. Moonbeam uses the following EVM precompiles:
- **[pallet-evm-precompile-simple](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_simple){target=\_blank}** - includes five basic precompiles: ECRecover, ECRecoverPublicKey, Identity, RIPEMD160, SHA256
- **[pallet-evm-precompile-blake2](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_blake2/struct.Blake2F.html){target=\_blank}** - includes the BLAKE2 precompile
- **[pallet-evm-precompile-bn128](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_bn128/index.html){target=\_blank}** - includes three BN128 precompiles: BN128Add, BN128Mul, and BN128Pairing
- **[pallet-evm-precompile-modexp](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_modexp/struct.Modexp.html){target=\_blank}** - includes the modular exponentiation precompile
- **[pallet-evm-precompile-sha3fips](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_sha3fips/struct.Sha3FIPS256.html){target=\_blank}** -includes the standard SHA3 precompile
- **[pallet-evm-precompile-dispatch](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_dispatch/struct.Dispatch.html){target=\_blank}** - includes the dispatch precompile
You can find an overview of most of these precompiles on the [Ethereum MainNet Precompiled Contracts](/builders/ethereum/precompiles/utility/eth-mainnet/){target=\_blank} page.
## Native Interoperability {: #native-interoperability }
While Substrate allows developers to create blockchains, one of its most significant advantages is that it supports integration for native interoperability through relay chains like Polkadot and Kusama.
A relay chain is a central chain that connects several blockchains, known as parachains. Each parachain is a distinct blockchain with its runtime and state, but all are connected to and secured by the relay chain. Once connected, parachains can communicate via [Cross-Consensus Messaging (XCM)](/builders/interoperability/xcm/overview/){target=_blank} to exchange information and conduct transactions in the same language, enabling a wide range of interoperable applications.
Moonbeam and Moonriver have established XCM connections with a large number of parachains. You can see a visualization of all XCM integrations in this [XCM Channel Viewer](https://dotsama-channels.vercel.app/#/){target=_blank}.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/platform/tokens/
--- BEGIN CONTENT ---
---
title: Utility Tokens
description: Each of the Moonbeam networks require a utility token to function. Glimmer (GLMR) for Moonbeam on Polkadot and Moonriver (MOVR) for Moonriver on Kusama.
categories: Basics
---
# Introduction
As a decentralized smart contract platform, Moonbeam requires a utility token to function.
This token is central to the design of Moonbeam and cannot be removed without sacrificing essential functionality. The Moonbeam token uses include:
- Supporting the gas metering of smart contract execution
- Incentivizing collators and powering the mechanics around the creation of a decentralized node infrastructure on which the platform can run
- Facilitating the on-chain governance mechanism, including proposing referenda, electing council members, voting, etc.
- Paying for network transaction fees
## Glimmer Token {: #glimmer-token }
In the Moonbeam deployment on Polkadot MainNet, this token is called Glimmer, as in, “that smart contract call will cost 0.3 Glimmer.” The token symbol is GLMR.
You can find more information about Glimmer on the [Moonbeam Foundation](https://moonbeam.foundation/glimmer-token-tokenomics) website.
## Moonriver Token {: #moonriver-token }
In the Moonbeam deployment on Kusama (called Moonriver), this token is called Moonriver, as in, “that smart contract call will cost 0.003 Moonriver.” The token symbol will be MOVR.
You can find more information about Moonriver on the [Moonbeam Foundation](https://moonbeam.foundation/moonriver-token-tokenomics) website.
## DEV Token {: #dev-token }
In the Moonbeam TestNet (called Moonbase Alpha), the token is called DEV. This token can be acquired freely, as its only purpose is to drive development and testing on Moonbase Alpha.
You can get DEV tokens for testing on Moonbase Alpha once every 24 hours from the [Moonbase Alpha Faucet](https://faucet.moonbeam.network){target=\_blank}.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/platform/vision/
--- BEGIN CONTENT ---
---
title: The Moonbeam Vision | Multi-chain
description: Moonbeam is designed to enable a multi-chain future, where users and assets can move freely across many specialized and heterogeneous chains.
categories: Basics
---
# Our Vision for Moonbeam
We believe in a multi-chain future with many chains, and many users and assets on those chains. In this context, we have created Moonbeam: a smart contract platform that provides an Ethereum-compatible environment for building decentralized applications. Moonbeam was designed to serve these new kinds of assets and users that exist across two or more chains.
Existing smart contract platforms are designed to service the users and assets on a single, specific chain. By providing cross-chain smart contract functionality, Moonbeam allows developers to shift existing workloads and logic to Moonbeam and extend the reach of their applications to new users and assets on other chains.
Moonbeam's cross-chain integration is accomplished by becoming a [parachain](/learn/platform/glossary/#parachains) on the Polkadot network. The [Polkadot network](/learn/platform/glossary/#polkadot) provides integration and connectivity between parachains that are connected to the network and to other non-Polkadot-based chains, such as Ethereum and Bitcoin, via bridges.
## Who Benefits From Moonbeam {: #who-benefits-from-moonbeam }
There are three main audiences who can most benefit from Moonbeam's cross-chain functionality:
### Existing Ethereum-Based Projects {: #existing-ethereum-based-projects }
Projects that are struggling with cost and scalability challenges on Ethereum can use Moonbeam to:
- Move portions of their existing workloads and state off of Ethereum Layer 1 with minimal required changes.
- Implement a hybrid approach, where applications live on both Ethereum and Moonbeam simultaneously.
- Extend their reach to the Polkadot network and other chains that are connected to Polkadot.
### Polkadot Ecosystem Projects {: #polkadot-ecosystem-projects }
Ecosystem projects that need smart contract functionality can use Moonbeam to:
- Augment their existing parachains and parathreads.
- Add new functionality that is needed but not included on the main [Polkadot relay chain](/learn/platform/glossary/#relay-chain). For example, they could create a place where teams can crowdfund their projects, implement lockdrops, and process other, more complex financial transactions than are provided by base [Substrate](/learn/platform/glossary/#substrate) functionality.
- Leverage the mature and extensive Ethereum development toolchain.
### Developers of New DApps {: #developers-of-new-dapps }
Individuals and teams that want to try building on Polkadot can use Moonbeam to:
- Leverage the specialized functionality from Polkadot parachains while reaching users and assets on other chains.
- Compose functionality from Polkadot parachains by using Moonbeam as a lightweight integration layer that aggregates network services before presenting them to end users. Implementing a composed service using pre-built integrations on a smart contract platform will be a lot faster and easier (in many cases) than building a full Substrate runtime and performing the integrations yourself in the runtime.
## Key Features and Functionality {: #key-features-and-functionality }
Moonbeam achieves these goals with the following key features:
- **Decentralized and Permissionless** , providing a base requirement for censorship resistance and support for many existing and future DApp use cases.
- **Contains a Full EVM Implementation** , enabling Solidity-based smart contracts to be migrated with minimal change and with expected execution results.
- **Implements the Web3 RPC API** so that existing DApp front-ends can be migrated with minimal change required, and so existing Ethereum-based tools, such as Hardhat, Remix, and MetaMask, can be used without modification against Moonbeam.
- **Compatible with the Substrate Ecosystem Toolset** , including block explorers, front-end development libraries, and wallets, allowing developers and users to use the right tool for what they are trying to accomplish.
- **Native Cross-Chain Integration** via the Polkadot network and via token bridges, which allows for token movement, state visibility, and message passing with Ethereum and other chains.
- **On-Chain Governance** to allow stakeholders to quickly and forklessly evolve the base protocol according to developer and community needs.
This unique combination of elements fills a strategic market gap, while allowing Moonbeam to address future developer needs as the Polkadot network grows over time. Building your own chain with Substrate is powerful, but also comes with a number of additional responsibilities, such as learning and implementing the chain’s runtime in Rust, creating a token economy, and incentivizing a community of node operators.
For many developers and projects, an Ethereum-compatible smart contract approach will be much simpler and faster to implement. And by building these smart contracts on Moonbeam, developers can still integrate with other chains and get value from Polkadot-based network effects.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/platform/why-polkadot/
--- BEGIN CONTENT ---
---
title: Why Polkadot
description: Moonbeam is built on the Substrate framework and connected to the Polkadot network, adding speed and security to the platform.
categories: Basics
---
# Why We're Building on Polkadot
After extensive research, we decided to build Moonbeam using the [Substrate development framework](/learn/platform/glossary/#substrate) and to deploy Moonbeam as a [parachain](/learn/platform/glossary/#parachains) on the [Polkadot network](/learn/platform/glossary/#polkadot).
## Substrate Blockchain Framework {: #substrate-blockchain-framework }
Substrate is a good technical fit for Moonbeam. By building on top of this framework, we can leverage the extensive functionality that Substrate includes out-of-the-box, rather than building it ourselves. This includes peer-to-peer networking, consensus mechanisms, governance functionality, an EVM implementation, and more.
Overall, using Substrate will dramatically reduce the time and implementation effort needed to implement Moonbeam. Substrate allows a great degree of customization, which is necessary in order to achieve our Ethereum compatibility goals. And, by using Rust, we benefit from both safety guarantees and performance gains.
## Polkadot Network and Ecosystem {: #polkadot-network-and-ecosystem }
The Polkadot network is also a good fit for Moonbeam. As a parachain on Polkadot, Moonbeam will be able to directly integrate with — and move tokens between — any other parachains and parathreads on the network.
We can also leverage any of the bridges that are independently built to connect non-Polkadot chains to Polkadot, including bridges to Ethereum. Polkadot’s interoperability model uniquely supports Moonbeam’s cross-chain integration goals and is a key enabling technology to support the Moonbeam vision.
But perhaps just as important as the technical criteria above, we are impressed with the people in the Polkadot ecosystem. This includes individuals at Parity, the Web3 Foundation, and other projects in the ecosystem. We have built many valuable relationships and find the people to be both extremely talented and the kind of people we want to be around.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/ethereum/dev-env/openzeppelin/overview/
--- BEGIN CONTENT ---
---
title: An Overview of OpenZeppelin on Moonbeam
description: Learn how to use OpenZeppelin products for creating and managing Solidity smart contracts on Moonbeam, thanks to its Ethereum compatibility features.
categories: Basics, Ethereum Toolkit
---
# OpenZeppelin
## Introduction {: #introduction }
[OpenZeppelin](https://www.openzeppelin.com){target=\_blank} is well known in the Ethereum developer community as their set of audited smart contracts and libraries are a standard in the industry. For example, most of the tutorials that show developers how to deploy an ERC-20 token use OpenZeppelin contracts.
You can find more information about OpenZeppelin on their [documentation site](https://docs.openzeppelin.com){target=\_blank}.
As part of its Ethereum compatibility features, OpenZeppelin products can be seamlessly used on Moonbeam. This page will provide information on different OpenZeppelin solutions that you can test.
## OpenZeppelin on Moonbeam {: #openzeppelin-on-moonbeam }
Currently, the following OpenZeppelin products/solutions work on the different networks available on Moonbeam:
| **Product** | **Moonbeam** | **Moonriver** | **Moonbase Alpha** | **Moonbase Dev Node** |
|:---------------------:|:------------:|:-------------:|:------------------:|:---------------------:|
| Contracts & libraries | ✓ | ✓ | ✓ | ✓ |
| Contracts Wizard | ✓ | ✓ | ✓ | ✓ |
You will find a corresponding tutorial for each product in the following links:
- [**Contracts Wizard**](/builders/ethereum/dev-env/openzeppelin/contracts/#openzeppelin-contract-wizard) — where you'll find a guide on how to use OpenZeppelin web-based wizard to create different token contracts with different functionalities
- [**Contracts & libraries**](/builders/ethereum/dev-env/openzeppelin/contracts/#deploying-openzeppelin-contracts-on-moonbeam) — where you'll find tutorials to deploy the most common token contracts using OpenZeppelin's templates: ERC-20, ERC-721 and ERC-1155
The information presented herein has been provided by third parties and is made available solely for general information purposes. Moonbeam does not endorse any project listed and described on the Moonbeam Doc Website (https://docs.moonbeam.network/). Moonbeam Foundation does not warrant the accuracy, completeness or usefulness of this information. Any reliance you place on such information is strictly at your own risk. Moonbeam Foundation disclaims all liability and responsibility arising from any reliance placed on this information by you or by anyone who may be informed of any of its contents. All statements and/or opinions expressed in these materials are solely the responsibility of the person or entity providing those materials and do not necessarily represent the opinion of Moonbeam Foundation. The information should not be construed as professional or financial advice of any kind. Advice from a suitably qualified professional should always be sought in relation to any particular matter or circumstance. The information herein may link to or integrate with other websites operated or content provided by third parties, and such other websites may link to this website. Moonbeam Foundation has no control over any such other websites or their content and will have no liability arising out of or related to such websites or their content. The existence of any such link does not constitute an endorsement of such websites, the content of the websites, or the operators of the websites. These links are being provided to you only as a convenience and you release and hold Moonbeam Foundation harmless from any and all liability arising from your use of this information or the information provided by any third-party website or service.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/ethereum/precompiles/overview/
--- BEGIN CONTENT ---
---
title: Solidity Precompiles
description: An overview of the available Solidity precompiles on Moonbeam. Precompiles enable you to interact with Substrate features using the Ethereum API.
categories: Reference, Basics
---
# Overview of the Precompiled Contracts on Moonbeam
## Overview {: #introduction }
On Moonbeam, a precompiled contract is native Substrate code that has an Ethereum-style address and can be called using the Ethereum API, like any other smart contract. The precompiles allow you to call the Substrate runtime directly which is not normally accessible from the Ethereum side of Moonbeam.
The Substrate code responsible for implementing precompiles can be found in the [EVM pallet](/learn/platform/technology/#evm-pallet){target=\_blank}. The EVM pallet includes the [standard precompiles found on Ethereum and some additional precompiles that are not specific to Ethereum](https://github.com/polkadot-evm/frontier/tree/master/frame/evm/precompile){target=\_blank}. It also provides the ability to create and execute custom precompiles through the generic [`Precompiles` trait](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm/trait.Precompile.html){target=\_blank}. There are several custom Moonbeam-specific precompiles that have been created, all of which can be found in the [Moonbeam codebase](https://github.com/moonbeam-foundation/moonbeam/tree/master/precompiles){target=\_blank}. It is important to highlight that the precompiles from this list with the `CallableByContract` check are not callable inside the contract constructor.
The Ethereum precompiled contracts contain complex functionality that is computationally intensive, such as hashing and encryption. The custom precompiled contracts on Moonbeam provide access to Substrate-based functionality such as staking, governance, XCM-related functions, and more.
The Moonbeam-specific precompiles can be interacted with through familiar and easy-to-use Solidity interfaces using the Ethereum API, which are ultimately used to interact with the underlying Substrate interface. This flow is depicted in the following diagram:

!!! note
There can be some unintended consequences when using the precompiled contracts on Moonbeam. Please refer to the [Security Considerations](/learn/core-concepts/security/){target=\_blank} page for more information.
## Precompiled Contract Addresses {: #precompiled-contract-addresses }
The precompiled contracts are categorized by address and based on the origin network. If you were to convert the precompiled addresses to decimal format, and break them into categories by numeric value, the categories are as follows:
- **0-1023** - [Ethereum MainNet precompiles](#ethereum-mainnet-precompiles)
- **1024-2047** - precompiles that are [not in Ethereum and not Moonbeam specific](#non-moonbeam-specific-nor-ethereum-precomiles)
- **2048-4095** - [Moonbeam specific precompiles](#moonbeam-specific-precompiles)
### Ethereum MainNet Precompiles {: #ethereum-mainnet-precompiles }
=== "Moonbeam"
| Contract | Address |
|:---------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [ECRECOVER](/builders/ethereum/precompiles/utility/eth-mainnet/#verify-signatures-with-ecrecover){target=\_blank} | 0x0000000000000000000000000000000000000001 |
| [SHA256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha256){target=\_blank} | 0x0000000000000000000000000000000000000002 |
| [RIPEMD160](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-ripemd-160){target=\_blank} | 0x0000000000000000000000000000000000000003 |
| [Identity](/builders/ethereum/precompiles/utility/eth-mainnet/#the-identity-function){target=\_blank} | 0x0000000000000000000000000000000000000004 |
| [Modular Exponentiation](/builders/ethereum/precompiles/utility/eth-mainnet/#modular-exponentiation){target=\_blank} | 0x0000000000000000000000000000000000000005 |
| [BN128Add](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128add){target=\_blank} | 0x0000000000000000000000000000000000000006 |
| [BN128Mul](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128mul){target=\_blank} | 0x0000000000000000000000000000000000000007 |
| [BN128Pairing](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128pairing){target=\_blank} | 0x0000000000000000000000000000000000000008 |
| [Blake2](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_blake2/struct.Blake2F.html){target=\_blank} | 0x0000000000000000000000000000000000000009 |
| [P256Verify](https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md){target=\_blank} | 0x0000000000000000000000000000000000000100 |
=== "Moonriver"
| Contract | Address |
|:---------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [ECRECOVER](/builders/ethereum/precompiles/utility/eth-mainnet/#verify-signatures-with-ecrecover){target=\_blank} | 0x0000000000000000000000000000000000000001 |
| [SHA256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha256){target=\_blank} | 0x0000000000000000000000000000000000000002 |
| [RIPEMD160](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-ripemd-160){target=\_blank} | 0x0000000000000000000000000000000000000003 |
| [Identity](/builders/ethereum/precompiles/utility/eth-mainnet/#the-identity-function){target=\_blank} | 0x0000000000000000000000000000000000000004 |
| [Modular Exponentiation](/builders/ethereum/precompiles/utility/eth-mainnet/#modular-exponentiation){target=\_blank} | 0x0000000000000000000000000000000000000005 |
| [BN128Add](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128add){target=\_blank} | 0x0000000000000000000000000000000000000006 |
| [BN128Mul](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128mul){target=\_blank} | 0x0000000000000000000000000000000000000007 |
| [BN128Pairing](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128pairing){target=\_blank} | 0x0000000000000000000000000000000000000008 |
| [Blake2](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_blake2/struct.Blake2F.html){target=\_blank} | 0x0000000000000000000000000000000000000009 |
| [P256Verify](https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md){target=\_blank} | 0x0000000000000000000000000000000000000100 |
=== "Moonbase Alpha"
| Contract | Address |
|:---------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [ECRECOVER](/builders/ethereum/precompiles/utility/eth-mainnet/#verify-signatures-with-ecrecover){target=\_blank} | 0x0000000000000000000000000000000000000001 |
| [SHA256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha256){target=\_blank} | 0x0000000000000000000000000000000000000002 |
| [RIPEMD160](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-ripemd-160){target=\_blank} | 0x0000000000000000000000000000000000000003 |
| [Identity](/builders/ethereum/precompiles/utility/eth-mainnet/#the-identity-function){target=\_blank} | 0x0000000000000000000000000000000000000004 |
| [Modular Exponentiation](/builders/ethereum/precompiles/utility/eth-mainnet/#modular-exponentiation){target=\_blank} | 0x0000000000000000000000000000000000000005 |
| [BN128Add](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128add){target=\_blank} | 0x0000000000000000000000000000000000000006 |
| [BN128Mul](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128mul){target=\_blank} | 0x0000000000000000000000000000000000000007 |
| [BN128Pairing](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128pairing){target=\_blank} | 0x0000000000000000000000000000000000000008 |
| [Blake2](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_blake2/struct.Blake2F.html){target=\_blank} | 0x0000000000000000000000000000000000000009 |
| [P256Verify](https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md){target=\_blank} | 0x0000000000000000000000000000000000000100 |
### Non-Moonbeam Specific nor Ethereum Precompiles {: #non-moonbeam-specific-nor-ethereum-precompiles }
=== "Moonbeam"
| Contract | Address |
|:--------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [SHA3FIPS256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha3fips256){target=\_blank} | 0x0000000000000000000000000000000000000400 |
| Dispatch [Removed] | 0x0000000000000000000000000000000000000401 |
| [ECRecoverPublicKey](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_simple/struct.ECRecoverPublicKey.html){target=\_blank} | 0x0000000000000000000000000000000000000402 |
=== "Moonriver"
| Contract | Address |
|:--------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [SHA3FIPS256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha3fips256){target=\_blank} | 0x0000000000000000000000000000000000000400 |
| Dispatch [Removed] | 0x0000000000000000000000000000000000000401 |
| [ECRecoverPublicKey](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_simple/struct.ECRecoverPublicKey.html){target=\_blank} | 0x0000000000000000000000000000000000000402 |
=== "Moonbase Alpha"
| Contract | Address |
|:-------------------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [SHA3FIPS256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha3fips256){target=\_blank} | 0x0000000000000000000000000000000000000400 |
| Dispatch [Removed] | 0x0000000000000000000000000000000000000401 |
| [ECRecoverPublicKey](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_simple/struct.ECRecoverPublicKey.html){target=\_blank} | 0x0000000000000000000000000000000000000402 |
### Moonbeam Specific Precompiles {: #moonbeam-specific-precompiles }
=== "Moonbeam"
| Contract | Address |
|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------:|
| [Parachain Staking](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/parachain-staking/StakingInterface.sol){target=\_blank} | {{networks.moonbeam.precompiles.staking}} |
| [Crowdloan Rewards](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/crowdloan-rewards/CrowdloanInterface.sol){target=\_blank} | {{networks.moonbeam.precompiles.crowdloan}} |
| [ERC-20 Interface](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/balances-erc20/ERC20.sol){target=\_blank} | {{networks.moonbeam.precompiles.erc20}} |
| Democracy [Removed] | {{networks.moonbeam.precompiles.democracy}} |
| [X-Tokens](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xtokens/Xtokens.sol){target=\_blank} | {{networks.moonbeam.precompiles.xtokens}} |
| [Relay Encoder](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/relay-encoder/RelayEncoder.sol){target=\_blank} | {{networks.moonbeam.precompiles.relay_encoder}} |
| [XCM Transactor V1](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v1/XcmTransactorV1.sol){target=\_blank} | {{networks.moonbeam.precompiles.xcm_transactor_v1}} |
| [Author Mapping](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/author-mapping/AuthorMappingInterface.sol){target=\_blank} | {{networks.moonbeam.precompiles.author_mapping}} |
| [Batch](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/batch/Batch.sol){target=\_blank} | {{networks.moonbeam.precompiles.batch}} |
| [Randomness](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/randomness/Randomness.sol){target=\_blank} | {{networks.moonbeam.precompiles.randomness}} |
| [Call Permit](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/call-permit/CallPermit.sol){target=\_blank} | {{networks.moonbeam.precompiles.call_permit}} |
| [Proxy](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/proxy/Proxy.sol){target=\_blank} | {{networks.moonbeam.precompiles.proxy}} |
| [XCM Utilities](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-utils/XcmUtils.sol){target=\_blank} | {{networks.moonbeam.precompiles.xcm_utils}} |
| [XCM Transactor V2](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v2/XcmTransactorV2.sol){target=\_blank} | {{networks.moonbeam.precompiles.xcm_transactor_v2}} |
| [Council Collective [Removed]](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbeam.precompiles.collective_council}} |
| [Technical Committee Collective [Removed]](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbeam.precompiles.collective_tech_committee}} |
| [Treasury Council Collective](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbeam.precompiles.collective_treasury}} |
| [Referenda](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/referenda/Referenda.sol){target=\_blank} | {{networks.moonbeam.precompiles.referenda}} |
| [Conviction Voting](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/conviction-voting/ConvictionVoting.sol){target=\_blank} | {{networks.moonbeam.precompiles.conviction_voting}} |
| [Preimage](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/preimage/Preimage.sol){target=\_blank} | {{networks.moonbeam.precompiles.preimage}} |
| [OpenGov Tech Committee](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbeam.precompiles.collective_opengov_tech_committee}} |
| [Precompile Registry](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/precompile-registry/PrecompileRegistry.sol){target=\_blank} | {{networks.moonbeam.precompiles.registry}} |
| [GMP](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/gmp/Gmp.sol){target=\_blank} | {{networks.moonbeam.precompiles.gmp}} |
| [XCM Transactor V3](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v3/XcmTransactorV3.sol){target=\_blank} | {{networks.moonbeam.precompiles.xcm_transactor_v3}} |
| [XCM interface](https://github.com/Moonsong-Labs/moonkit/blob/main/precompiles/pallet-xcm/XcmInterface.sol){target=\_blank} | {{networks.moonbeam.precompiles.xcm_interface}} |
| [Identity](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/identity/Identity.sol){target=\_blank} | {{networks.moonbeam.precompiles.identity}} |
=== "Moonriver"
| Contract | Address |
|:-------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------:|
| [Parachain Staking](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/parachain-staking/StakingInterface.sol){target=\_blank} | {{networks.moonriver.precompiles.staking}} |
| [Crowdloan Rewards](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/crowdloan-rewards/CrowdloanInterface.sol){target=\_blank} | {{networks.moonriver.precompiles.crowdloan}} |
| [ERC-20 Interface](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/balances-erc20/ERC20.sol){target=\_blank} | {{networks.moonriver.precompiles.erc20}} |
| Democracy [Disabled] | {{networks.moonriver.precompiles.democracy}} |
| [X-Tokens](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xtokens/Xtokens.sol){target=\_blank} | {{networks.moonriver.precompiles.xtokens}} |
| [Relay Encoder](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/relay-encoder/RelayEncoder.sol){target=\_blank} | {{networks.moonriver.precompiles.relay_encoder}} |
| [XCM Transactor V1](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v1/XcmTransactorV1.sol){target=\_blank} | {{networks.moonriver.precompiles.xcm_transactor_v1}} |
| [Author Mapping](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/author-mapping/AuthorMappingInterface.sol){target=\_blank} | {{networks.moonriver.precompiles.author_mapping}} |
| [Batch](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/batch/Batch.sol){target=\_blank} | {{networks.moonriver.precompiles.batch}} |
| [Randomness](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/randomness/Randomness.sol){target=\_blank} | {{networks.moonriver.precompiles.randomness}} |
| [Call Permit](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/call-permit/CallPermit.sol){target=\_blank} | {{networks.moonriver.precompiles.call_permit}} |
| [Proxy](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/proxy/Proxy.sol){target=\_blank} | {{networks.moonriver.precompiles.proxy}} |
| [XCM Utilities](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-utils/XcmUtils.sol){target=\_blank} | {{networks.moonriver.precompiles.xcm_utils}} |
| [XCM Transactor V2](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v2/XcmTransactorV2.sol){target=\_blank} | {{networks.moonriver.precompiles.xcm_transactor_v2}} |
| [Council Collective [Removed]](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonriver.precompiles.collective_council}} |
| [Technical Committee Collective [Removed]](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonriver.precompiles.collective_tech_committee}} |
| [Treasury Council Collective](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonriver.precompiles.collective_treasury}} |
| [Referenda](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/referenda/Referenda.sol){target=\_blank} | {{networks.moonriver.precompiles.referenda}} |
| [Conviction Voting](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/conviction-voting/ConvictionVoting.sol){target=\_blank} | {{networks.moonriver.precompiles.conviction_voting}} |
| [Preimage](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/preimage/Preimage.sol){target=\_blank} | {{networks.moonriver.precompiles.preimage}} |
| [OpenGov Tech Committee](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonriver.precompiles.collective_opengov_tech_committee}} |
| [Precompile Registry](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/precompile-registry/PrecompileRegistry.sol){target=\_blank} | {{networks.moonriver.precompiles.registry}} |
| [GMP](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/gmp/Gmp.sol){target=\_blank} | {{networks.moonriver.precompiles.gmp}} |
| [XCM Transactor V3](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v3/XcmTransactorV3.sol){target=\_blank} | {{networks.moonriver.precompiles.xcm_transactor_v3}} |
| [XCM interface](https://github.com/Moonsong-Labs/moonkit/blob/main/precompiles/pallet-xcm/XcmInterface.sol){target=\_blank} | {{networks.moonriver.precompiles.xcm_interface}} |
| [Identity](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/identity/Identity.sol){target=\_blank} | {{networks.moonriver.precompiles.identity}} |
=== "Moonbase Alpha"
| Contract | Address |
|:--------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------:|
| [Parachain Staking](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/parachain-staking/StakingInterface.sol){target=\_blank} | {{networks.moonbase.precompiles.staking}} |
| [Crowdloan Rewards](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/crowdloan-rewards/CrowdloanInterface.sol){target=\_blank} | {{networks.moonbase.precompiles.crowdloan}} |
| [ERC-20 Interface](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/balances-erc20/ERC20.sol){target=\_blank} | {{networks.moonbase.precompiles.erc20}} |
| Democracy [Removed] | {{networks.moonbase.precompiles.democracy}} |
| [X-Tokens](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xtokens/Xtokens.sol){target=\_blank} | {{networks.moonbase.precompiles.xtokens}} |
| [Relay Encoder](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/relay-encoder/RelayEncoder.sol){target=\_blank} | {{networks.moonbase.precompiles.relay_encoder}} |
| [XCM Transactor V1](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v1/XcmTransactorV1.sol){target=\_blank} | {{networks.moonbase.precompiles.xcm_transactor_v1}} |
| [Author Mapping](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/author-mapping/AuthorMappingInterface.sol){target=\_blank} | {{networks.moonbase.precompiles.author_mapping}} |
| [Batch](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/batch/Batch.sol){target=\_blank} | {{networks.moonbase.precompiles.batch}} |
| [Randomness](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/randomness/Randomness.sol){target=\_blank} | {{networks.moonbase.precompiles.randomness}} |
| [Call Permit](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/call-permit/CallPermit.sol){target=\_blank} | {{networks.moonbase.precompiles.call_permit}} |
| [Proxy](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/proxy/Proxy.sol){target=\_blank} | {{networks.moonbase.precompiles.proxy}} |
| [XCM Utilities](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-utils/XcmUtils.sol){target=\_blank} | {{networks.moonbase.precompiles.xcm_utils}} |
| [XCM Transactor V2](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v2/XcmTransactorV2.sol){target=\_blank} | {{networks.moonbase.precompiles.xcm_transactor_v2}} |
| [Council Collective [Removed]](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbase.precompiles.collective_council}} |
| [Technical Committee Collective [Removed]](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbase.precompiles.collective_tech_committee}} |
| [Treasury Council Collective](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbase.precompiles.collective_treasury}} |
| [Referenda](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/referenda/Referenda.sol){target=\_blank} | {{networks.moonbase.precompiles.referenda}} |
| [Conviction Voting](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/conviction-voting/ConvictionVoting.sol){target=\_blank} | {{networks.moonbase.precompiles.conviction_voting}} |
| [Preimage](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/preimage/Preimage.sol){target=\_blank} | {{networks.moonbase.precompiles.preimage}} |
| [OpenGov Tech Committee](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbase.precompiles.collective_opengov_tech_committee}} |
| [Precompile Registry](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/precompile-registry/PrecompileRegistry.sol){target=\_blank} | {{networks.moonbase.precompiles.registry}} |
| [GMP](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/gmp/Gmp.sol){target=\_blank} | {{networks.moonbase.precompiles.gmp}} |
| [XCM Transactor V3](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v3/XcmTransactorV3.sol){target=\_blank} | {{networks.moonbase.precompiles.xcm_transactor_v3}} |
| [XCM Interface](https://github.com/Moonsong-Labs/moonkit/blob/main/precompiles/pallet-xcm/XcmInterface.sol){target=\_blank} | {{networks.moonbeam.precompiles.xcm_interface}} |
| [Identity](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/identity/Identity.sol){target=\_blank} | {{networks.moonbase.precompiles.identity}} |
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/get-started/create-account/
--- BEGIN CONTENT ---
---
title: Create an Account
description: To begin developing on Moonbeam, you must create an account. This guide will provide you with the information needed to create one to use on Moonbeam.
categories: Basics
---
# Create an Account
## Introduction {: #introduction }
To get started developing on Moonbeam, developers must create an account. The most prevalent approach involves leveraging a wallet application, which facilitates generating and managing cryptographic keys essential for interacting with Moonbeam.
Moonbeam uses H160 Ethereum-style accounts and ECDSA keys, represented in 20-byte addresses. If you already have an Ethereum account and its private key or mnemonic, you can use your account on Moonbeam.
This guide will walk you through the step-by-step process of creating an account on Moonbeam. Whether you're new to blockchain technology or an experienced Ethereum user, this guide will provide all the information you need to get started.
!!! note
This guide does not pertain to a local Moonbeam development node. If you are using a development node, you don't need to worry about creating an account, as the node comes with ten pre-funded accounts for testing purposes. Please refer to the [Getting Started with a Local Moonbeam Development Node](/builders/get-started/networks/moonbeam-dev/){target=\_blank} guide for more information.
## Choose a Wallet {: #choose-a-wallet }
A wallet is a software or hardware tool that allows you to securely store, manage, and interact with your digital assets, such as tokens or coins. Wallets store your private keys, which are essential for authorizing transactions on the network.
You can review a list of wallets on the [Moonbeam DApp Directory](https://apps.moonbeam.network/moonbeam/app-dir?cat=wallets){target=\_blank}.

The list of wallets on the dApp is not exhaustive and may only cover some of the available options. You should be able to use any Ethereum-compatible wallet to generate an address and its associated private key.
You can also check out any of the wallets in the [Connect to Moonbeam](/tokens/connect/){target=\_blank} section of the docs.
## Use Your Wallet to Create an Account {: #use-your-wallet-to-create-an-account }
After you've selected a wallet and downloaded it, you'll most likely be prompted to create a new account or import an existing one the first time you open it. You'll want to create a new account.
Depending on the wallet, when creating an account, you may be prompted to backup and restore a seed phrase, also referred to as a mnemonic or recovery phrase. This phrase is a sequence of generated words that serve as a backup mechanism for private keys. They typically consist of 12 to 24 words randomly selected from a predefined list. Seed phrases are used to derive private keys deterministically, meaning that the same sequence of words will always generate the same set of private keys. They are crucial for recovering access to a cryptocurrency wallet in case of loss or device failure. **Make sure you save the phrase in a safe place; if you lose access to this phrase, you'll lose access to any funds you hold in your account.**
After saving your seed phrase, you can start developing on Moonbeam. Many wallets offer the option to export the private key linked to your account. By doing so, you can utilize your private key instead of the seed phrase during development. However, taking adequate precautions to securely store your private key or seed phrase while developing is essential.
And that's it! Before sending your first transaction on a Moonbeam-based network, ensure you have the necessary [network configurations for your chosen network](/builders/get-started/networks/){target=\_blank} and an [RPC endpoint](/builders/get-started/endpoints/){target=\_blank} for the network. Once you have these items, you'll be able to follow along with tutorials like the [How to use Ethers.js](/builders/ethereum/libraries/ethersjs/){target=\_blank} or the [How to use Web3.js](/builders/ethereum/libraries/web3js/){target=\_blank} to send a transaction.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/get-started/explorers/
--- BEGIN CONTENT ---
---
title: Block Explorers
description: An overview of the currently available block explorers that may be used to navigate the Substrate and Ethereum layers of Moonbeam.
categories: Basics
---
# Block Explorers
## Introduction {: #introduction }
Block explorers can be thought of as search engines for the blockchain. They allow users to search for information such as balances, contracts, and transactions. More advanced block explorers even offer indexing capabilities, which enable them to provide a complete set of information, such as ERC-20 tokens in the network. They might even offer API services to access it via external services.
Moonbeam provides two different kinds of explorers: ones to query the Ethereum API and others dedicated to the Substrate API. All EVM-based transactions are accessible via the Ethereum API, while the Substrate API can be relied upon for Substrate-native functions such as governance and staking. The Substrate API also includes information about the EVM-based transactions, but only limited information is shown.
## Quick Links {: #quick-links }
=== "Moonbeam"
| Block Explorer | Type | URL |
|:--------------:|:---------:|:-------------------------------------------------------------------------------------------------------------------------------------:|
| Moonscan | EVM | [https://moonbeam.moonscan.io/](https://moonbeam.moonscan.io){target=\_blank} |
| Expedition | EVM | [https://moonbeam-explorer.netlify.app/?network=Moonbeam](https://moonbeam-explorer.netlify.app/?network=Moonbeam){target=\_blank} |
| Subscan | Substrate | [https://moonbeam.subscan.io/](https://moonbeam.subscan.io){target=\_blank} |
| Polkadot.js | Substrate | [https://polkadot.js.org/apps/#/explorer](https://polkadot.js.org/apps/?rpc=wss://wss.api.moonbeam.network#/explorer){target=\_blank} |
=== "Moonriver"
| Block Explorer | Type | URL |
|:--------------:|:---------:|:-----------------------------------------------------------------------------------------------------------------------------------------------:|
| Moonscan | EVM | [https://moonriver.moonscan.io/](https://moonriver.moonscan.io){target=\_blank} |
| Expedition | EVM | [https://moonbeam-explorer.netlify.app/?network=Moonriver](https://moonbeam-explorer.netlify.app/?network=Moonriver){target=\_blank} |
| Subscan | Substrate | [https://moonriver.subscan.io/](https://moonriver.subscan.io){target=\_blank} |
| Polkadot.js | Substrate | [https://polkadot.js.org/apps/#/explorer](https://polkadot.js.org/apps/?rpc=wss://wss.api.moonrvier.moonbeam.network#/explorer){target=\_blank} |
=== "Moonbase Alpha"
| Block Explorer | Type | URL |
|:--------------:|:---------:|:----------------------------------------------------------------------------------------------------------------------------------------------:|
| Moonscan | EVM | [https://moonbase.moonscan.io/](https://moonbase.moonscan.io){target=\_blank} |
| Expedition | EVM | [https://moonbeam-explorer.netlify.app/?network=MoonbaseAlpha](https://moonbeam-explorer.netlify.app/?network=MoonbaseAlpha){target=\_blank} |
| Subscan | Substrate | [https://moonbase.subscan.io/](https://moonbase.subscan.io){target=\_blank} |
| Polkadot.js | Substrate | [https://polkadot.js.org/apps/#/explorer](https://polkadot.js.org/apps/?rpc=wss://wss.api.moonbase.moonbeam.network#/explorer){target=\_blank} |
=== "Moonbeam Dev Node"
| Block Explorer | Type | URL |
|:--------------:|:---------:|:-------------------------------------------------------------------------------------------------------------------------------------------------:|
| Expedition | EVM | [https://moonbeam-explorer.netlify.app/?network=MoonbeamDevNode](https://moonbeam-explorer.netlify.app/?network=MoonbeamDevNode){target=\_blank} |
| Polkadot.js | Substrate | [https://polkadot.js.org/apps/#/explorer](https://polkadot.js.org/apps/?rpc=wss://ws%3A%2F%2F127.0.0.1%3A9944#/explorer){target=\_blank} |
## Ethereum API {: #ethereum-api }
### Moonscan {: #Moonscan }
[Moonscan](https://moonscan.io){target=\_blank} is the primary Ethereum API block explorer for Moonbeam-based networks. Built by the Etherscan team, Moonscan provides a powerful, intuitive, and feature-rich experience. In addition to its comprehensive transaction and block data, Moonscan provides a number of [statistics and charts](https://moonbeam.moonscan.io/charts){target=\_blank}, such as average gas price, daily transactions, and block size charts.
Other Moonscan features include:
- [Collator leaderboard](https://moonbeam.moonscan.io/collators){target=\_blank} ranking collators by performance
- [Contract source code verification](/builders/ethereum/verify-contracts/block-explorers/){target=\_blank}, accessible both via a web interface and an API
- Ability to read and write state data of verified smart contracts
- [Token approvals](https://moonscan.io/tokenapprovalchecker){target=\_blank} where you can view and revoke any of your prior token approvals
- [Adding token information](/builders/get-started/token-profile/){target=\_blank} and creating a profile for ERC-20s, ERC-721s, and ERC-1155s deployed to Moonbeam-based networks. The profile can include links to your project, social media, price data, and other information pertaining to your token

### Expedition {: #expedition }
A Moonbeam-themed version of the [Expedition](https://github.com/xops/expedition){target=\_blank} explorer can be found in [this link](https://moonbeam-explorer.netlify.app){target=\_blank}. It is a basic JSON-RPC based explorer.
By default, the explorer is connected to Moonbeam. However, you can switch to Moonriver or Moonbase Alpha, or connect it to a local dev node by following the next steps:
1. Click on the network text, where you'll be able to select between all different networks, including a **Moonbeam Development Node** running on `{{ networks.development.rpc_url }}`
2. In the case you want to connect to a specific RPC URL, select **Add Custom Chain** and enter the URL. For example, `http://localhost:9937`

## Substrate API {: #substrate-api }
### Subscan {: #subscan }
[Subscan](https://moonbeam.subscan.io){target=\_blank} is the primary Substrate API block explorer for Moonbeam-based networks. Subscan is capable of parsing standard or custom modules. For example, this is useful to display information regarding the Staking, Governance, and EVM pallets (or modules). The code is all open-source and can be found in the [Subscan Essentials GitHub repo](https://github.com/subscan-explorer/subscan-essentials){target=\_blank}.

### Polkadot.js {: #polkadotjs }
While not a full-featured block explorer, Polkadot.js Apps is a convenient option especially for users running local development nodes to view events and query transaction hashes. Polkadot.js Apps uses the WebSocket endpoint to interact with the Network. You can easily connect to [Moonbeam](https://polkadot.js.org/apps/?rpc=wss://wss.api.moonbeam.network#/explorer){target=\_blank}, [Moonriver](https://polkadot.js.org/apps/?rpc=wss://wss.api.moonriver.moonbase.moonbeam.network#/explorer){target=\_blank}, or [Moonbase Alpha](https://polkadot.js.org/apps/?rpc=wss://wss.api.moonbase.moonbeam.network#/explorer){target=\_blank}.

To connect it to a Moonbeam development node, you can follow the steps in the [Connecting Polkadot.js Apps to a Local Moonbeam Node](/builders/get-started/networks/moonbeam-dev/#connecting-polkadot-js-apps-to-a-local-moonbeam-node){target=\_blank} section of the [Getting Started with a Moonbeam Development Node](/builders/get-started/networks/moonbeam-dev/){target=\_blank} guide. The default port for this is `9944`.

--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/get-started/networks/moonbase/
--- BEGIN CONTENT ---
---
title: Moonbase Alpha Get Started Guide
description: The Moonbeam TestNet, named Moonbase Alpha, is the easiest way to get started with a Polkadot environment. Follow this tutorial to connect to the TestNet.
categories: Basics
---
# Get Started with Moonbase Alpha
## Network Endpoints {: #network-endpoints }
Moonbase Alpha has two types of endpoints available for users to connect to: one for HTTPS and one for WSS.
If you're looking for your own endpoints suitable for production use, you can check out the [Endpoint Providers](/builders/get-started/endpoints/#endpoint-providers){target=\_blank} section of our documentation. Otherwise, to get started quickly you can use one of the following public HTTPS or WSS endpoints.
=== "HTTPS"
| Provider | RPC URL | Limits |
|:-------------------:|:------------------------------------------------------------------:|:-----------:|
| Dwellir |
| 200 req/sec |
#### Relay Chain {: #relay-chain }
To connect to the Moonbase Alpha relay chain, you can use the following WS Endpoint:
| Provider | RPC URL |
|:--------:|:----------------------------------------------------------:|
| OpsLayer |
```wss://relay.api.moonbase.moonbeam.network```
|
## Quick Start {: #quick-start }
For the [Web3.js library](/builders/ethereum/libraries/web3js/){target=\_blank}, you can create a local Web3 instance and set the provider to connect to Moonbase Alpha (both HTTP and WS are supported):
```js
const { Web3 } = require('web3'); // Load Web3 library
.
.
.
// Create local Web3 instance - set Moonbase Alpha as provider
const web3 = new Web3('https://rpc.api.moonbase.moonbeam.network');
```
For the [Ethers.js library](/builders/ethereum/libraries/ethersjs/){target=\_blank}, define the provider by using `ethers.JsonRpcProvider(providerURL, {object})` and setting the provider URL to Moonbase Alpha:
```js
const ethers = require('ethers'); // Load Ethers library
const providerURL = 'https://rpc.api.moonbase.moonbeam.network';
// Define provider
const provider = new ethers.JsonRpcProvider(providerURL, {
chainId: 1287,
name: 'moonbase-alphanet'
});
```
Any Ethereum wallet should be able to generate a valid address for Moonbeam (for example, [MetaMask](https://metamask.io){target=\_blank}).
## Chain ID {: #chain-id }
Moonbase Alpha TestNet chain ID is: `1287`, which is `0x507` in hex.
## Block Explorers
For Moonbase Alpha, you can use any of the following block explorers:
- **Ethereum API (Etherscan Equivalent)** — [Moonscan](https://moonbase.moonscan.io){target=\_blank}
- **Ethereum API JSON-RPC based** — [Moonbeam Basic Explorer](https://moonbeam-explorer.netlify.app/?network=MoonbaseAlpha){target=\_blank}
- **Substrate API** — [Subscan](https://moonbase.subscan.io){target=\_blank} or [Polkadot.js Apps](https://polkadot.js.org/apps/?rpc=wss://wss.api.moonbase.moonbeam.network#/explorer){target=\_blank}
For more information on each of the available block explorers, please head to the [Block Explorers](/builders/get-started/explorers/){target=\_blank} section of the documentation.
## Connect MetaMask
If you already have MetaMask installed, you can easily connect MetaMask to the Moonbase Alpha TestNet:
!!! note
MetaMask will popup asking for permission to add Moonbase Alpha as a custom network. Once you approve permissions, MetaMask will switch your current network to Moonbase Alpha.
If you do not have MetaMask installed, or would like to follow a tutorial to get started, please check out the [Interacting with Moonbeam using MetaMask](/tokens/connect/metamask/){target=\_blank} guide.
## Configuration {: #configuration }
Please note the following gas configuration parameters. These values are subject to change in future runtime upgrades.
| Variable | Value |
|:---------------------:|:------------------------------------------:|
| Minimum gas price | {{ networks.moonbase.min_gas_price }} Gwei |
| Target block time | {{ networks.moonbase.block_time }} seconds |
| Block gas limit | {{ networks.moonbase.gas_block }} |
| Transaction gas limit | {{ networks.moonbase.gas_tx }} |
## Get Tokens {: #get-tokens }
To start building on Moonbase Alpha, you can get DEV tokens from the Moonbase Alpha Faucet. For specific amounts, you can always reach out directly to us via our community channels.
To request DEV tokens from the faucet, you can enter your address on the [Moonbase Alpha Faucet](https://faucet.moonbeam.network){target=\_blank} website. The faucet dispenses {{ networks.moonbase.website_faucet_amount }} every 24 hours.

!!! note
Moonbase Alpha DEV tokens have no value. Please don't spam the faucet with unnecessary requests.
## Demo DApps {: #Demo-DApps }
There are a variety of DApps deployed to Moonbase Alpha enabling you to experiment with various apps and integrations. You can also acquire a variety of test tokens through the [Moonbase ERC20 Minter](https://moonbase-minterc20.netlify.app){target=\_blank} or [Moonbeam Uniswap](https://moonbeam-swap.netlify.app/#/swap){target=\_blank} DApps. For example, [Moonbeam Uniswap](https://moonbeam-swap.netlify.app/#/swap){target=\_blank} can help you acquire cross-chain assets such as xcUNIT or xcKarura for testing XCM related functions. In the below table, you'll find each sample DApp, its associated URL, and GitHub repository.
### Quick Links {: #quick-links }
| DApp | Description | Repository |
|:------------------------------------------------------------------------------------------:|:------------------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------:|
| [Moonbase ERC-20 Minter](https://moonbase-minterc20.netlify.app){target=\_blank} | ERC-20 Faucet | [https://github.com/papermoonio/moonbase-mintableERC20](https://github.com/papermoonio/moonbase-mintableERC20){target=\_blank} |
| [Moonbeam Uniswap](https://moonbeam-swap.netlify.app/#/swap){target=\_blank} | Uniswap V2 Fork | [https://github.com/papermoonio/moonbeam-uniswap](https://github.com/papermoonio/moonbeam-uniswap){target=\_blank} |
| [MoonLotto Lottery](https://moonbase-moonlotto.netlify.app){target=\_blank} | TheGraph Demo | [Interface](https://github.com/papermoonio/moonlotto-interface){target=\_blank}, [Subgraph](https://github.com/papermoonio/moonlotto-subgraph){target=\_blank} |
| [Moonbeam WalletConnect](https://moonbeam-walletconnect-demo.netlify.app){target=\_blank} | WalletConnect Demo | [https://github.com/papermoonio/moonbeam-walletconnect-demo](https://github.com/papermoonio/moonbeam-walletconnect-demo){target=\_blank} |
| [MoonGas](https://moonbeam-gasinfo.netlify.app){target=\_blank} | Gas Price Tracker | [https://github.com/albertov19/moonbeam-gas-station](https://github.com/albertov19/moonbeam-gas-station){target=\_blank} |
!!! note
These DApps are intended for demonstration purposes only and may be incomplete or unsuitable for production deployments.
### Moonbase ERC20 Minter {: #moonbase-erc20-minter }
The [Moonbase ERC-20 Minter](https://moonbase-minterc20.netlify.app){target=\_blank} enables you to mint a variety of ERC-20 test tokens corresponding to the 8 planets of the solar system, and Pluto. To mint tokens, first press **Connect MetaMask** in the upper right hand corner. Then scroll to the **Mint Tokens** section and the choose desired ERC-20 contract. Press **Submit Tx** and confirm the transaction in MetaMask. Each mint will grant you 100 tokens, and you can mint tokens for each contract once per hour.

### Moonbeam Uniswap {: #moonbeam-uniswap }
[Moonbeam Uniswap](https://moonbeam-swap.netlify.app/#/swap){target=\_blank} is a fork of [Uniswap-V2](https://blog.uniswap.org/uniswap-v2){target=\_blank} deployed to Moonbase Alpha. Notably, Moonbeam Uniswap allows developers to easily make a swap to acquire [cross-chain assets](/builders/interoperability/xcm/xc20/){target=\_blank} such as xcKarura or xcUNIT for XCM testing purposes. To perform your first swap, take the following steps:
1. Press **Select a token**
2. Connect your MetaMask wallet and ensure you're on the Moonbase Alpha network
3. Press **Choose a List** on the prompt
4. Select **Moon Menu**
5. Search for or select your desired asset from the list then continue with the swap

!!! note
If you see only a partial list of assets under **Moon Menu**, your browser may have cached an older version of **Moon Menu**. Clearing the cache and re-adding **Moon Menu** will resolve this.
### MoonLotto Lottery {: #moonlotto-lottery }
[MoonLotto](https://moonbase-moonlotto.netlify.app){target=\_blank} is a simple lottery game on Moonbase Alpha derived from [The Graph's Example Subgraph](https://github.com/graphprotocol/example-subgraph){target=\_blank}. Purchasing a ticket costs 1 DEV and a winner is chosen each half hour if there are at least 10 participants. [MoonLotto.sol](https://github.com/papermoonio/moonlotto-subgraph/blob/main/contracts/MoonLotto.sol){target=\_blank} holds the contract logic for the lottery. To participate, take the following steps:
1. Connect your MetaMask wallet and ensure you're on the Moonbase Alpha network
2. Enter the address of the recipient of lotto ticket or check **I want to buy a ticket for my address**
3. Press **Submit on MetaMask** and confirm the transaction in MetaMask

### Moonbeam WalletConnect {: #moonbeam-walletconnect }
[Moonbeam WalletConnect](https://moonbeam-walletconnect-demo.netlify.app){target=\_blank} shows how easy it is to integrate [WalletConnect](https://walletconnect.com){target=\_blank} into your DApps and unlock support for a great variety of crypto wallets. Be sure to check out the [demo app repository](https://github.com/papermoonio/moonbeam-walletconnect-demo){target=\_blank} to see exactly how the WalletConnect integration works. To get started, you can take the following steps:
1. Press **Connect Wallet**
2. Scan the QR code using a [wallet compatible with WalletConnect](https://walletguide.walletconnect.network/){target=\_blank}

### MoonGas {: #moongas }
[MoonGas](https://moonbeam-gasinfo.netlify.app){target=\_blank} is a convenient dashboard for viewing the minimum, maximum, and average gas price of transactions in the prior block across all Moonbeam networks. Note, these statistics can fluctuate widely by block and occasionally include outlier values. You can check out the [repository for MoonGas](https://github.com/albertov19/moonbeam-gas-station){target=\_blank}.
You'll notice that the minimum gas price for Moonbeam is {{ networks.moonbeam.min_gas_price }} Gwei, while the minimum for Moonriver is {{ networks.moonriver.min_gas_price }} Gwei and Moonbase Alpha is {{ networks.moonbase.min_gas_price }} Gwei. This difference stems from the [100 to 1 re-denomination of GLMR](https://moonbeam.network/news/moonbeam-foundation-announces-liquidity-programs-a-new-token-event-and-glmr-redenomination){target=\_blank} and thus the {{ networks.moonbeam.min_gas_price }} Gwei minimum on Moonbeam corresponds to a {{ networks.moonriver.min_gas_price }} Gwei minimum on Moonriver and a {{ networks.moonbase.min_gas_price }} Gwei on Moonbase.

--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/get-started/networks/moonbeam-dev/
--- BEGIN CONTENT ---
---
title: Run a Moonbeam Development Node
description: Follow this tutorial to learn how to spin up your first Moonbeam development node, how to configure it for development purposes, and connect to it.
categories: Basics
---
# Getting Started with a Local Moonbeam Development Node
## Introduction {: #introduction }
A Moonbeam development node is your own personal development environment for building and testing applications on Moonbeam. For Ethereum developers, it is comparable to the Hardhat Network. It enables you to get started quickly and easily without the overhead of a relay chain. You can spin up your node with the `--sealing` option to author blocks instantly, manually, or at a custom interval after transactions are received. By default, a block will be created when a transaction is received, which is similar to the default behavior of Hardhat Network's instamine feature.
If you follow this guide to the end, you will have a Moonbeam development node running in your local environment with 10 prefunded [accounts](#pre-funded-development-accounts).
!!! note
This tutorial was created using the {{ networks.development.build_tag }} tag of [Moonbase Alpha](https://github.com/moonbeam-foundation/moonbeam/releases/tag/{{ networks.development.build_tag }}){target=\_blank}. The Moonbeam platform and the [Frontier](https://github.com/polkadot-evm/frontier){target=\_blank} components it relies on for Substrate-based Ethereum compatibility are still under very active development.
The examples in this guide assume you have a MacOS or Ubuntu 22.04-based environment and will need to be adapted accordingly for Windows.
## Spin Up a Moonbeam Development Node {: #spin-up-a-node }
There are two ways to get started running a Moonbeam node. You can use [Docker to run a pre-built binary](#getting-started-with-docker) or you can [compile the binary locally](#getting-started-with-the-binary-file) and set up a development node yourself. Using Docker is a quick and convenient way to get started, as you won't have to install Substrate and all the dependencies, and you can skip the node-building process as well. It does require you to [install Docker](https://docs.docker.com/get-started/get-docker/){target=\_blank}. On the other hand, if you decide you want to go through the process of building your development node, it could take roughly 30 minutes or longer to complete, depending on your hardware.
### Spin Up a Node with Docker {: #getting-started-with-docker }
Using Docker enables you to spin up a node in a matter of seconds. Once you have Docker installed, you can take the following steps to spin up your node:
1. Execute the following command to download the latest Moonbeam image:
```bash
docker pull moonbeamfoundation/moonbeam:{{ networks.development.build_tag }}
```
The tail end of the console log should look like this:
2. Spin up a Moonbeam development node by running the following Docker command, which will launch the node in instant seal mode for local testing so that blocks are authored instantly as transactions are received:
=== "Ubuntu"
```bash
docker run --rm --name {{ networks.development.container_name }} --network host \
moonbeamfoundation/moonbeam:{{ networks.development.build_tag }} \
--dev --rpc-external
```
=== "MacOS"
```bash
docker run --rm --name {{ networks.development.container_name }} -p 9944:9944 \
moonbeamfoundation/moonbeam:{{ networks.development.build_tag }} \
--dev --rpc-external
```
=== "Windows"
```bash
docker run --rm --name {{ networks.development.container_name }} -p 9944:9944 ^
moonbeamfoundation/moonbeam:{{ networks.development.build_tag }} ^
--dev --rpc-external
```
!!! note
On MacOS with silicon chips, Docker images may perform poorly. To improve performance, try [spinning up a Node with a Binary File](#getting-started-with-the-binary-file).
If successful, you should see an output showing an idle state waiting for blocks to be authored:
docker run --rm --name moonbeam_development --network host \
moonbeamfoundation/moonbeam:v0.45.0 \
--dev --rpc-external
CLI parameter `--execution` has no effect anymore and will be removed in the future!
2025-07-10 09:04:26 Moonbeam Parachain Collator
2025-07-10 09:04:26 ✌️ version 0.46.0-d7df89e7161
2025-07-10 09:04:26 ❤️ by PureStake, 2019-2025
2025-07-10 09:04:26 📋 Chain specification: Moonbase Development Testnet
2025-07-10 09:04:26 🏷 Node name: black-and-white-sticks-9174
2025-07-10 09:04:26 👤 Role: AUTHORITY
2025-07-10 09:04:26 💾 Database: RocksDb at /tmp/substrateO3YeRz/chains/moonbase_dev/db/full
2025-07-10 09:04:26 🔨 Initializing Genesis block/state (state: 0xf7c4…5c0f, header-hash: 0x42bd…3b5b)
2025-07-10 09:04:26 Using default protocol ID "sup" because none is configured in the chain specs
2025-07-10 09:04:26 🏷 Local node identity is: 12D3KooWLcpczme2JeBEfLqmjqkzYVKTGKhhGmwSzHjRXGBVhDX7
2025-07-10 09:04:26 💻 Operating system: linux
2025-07-10 09:04:26 💻 CPU architecture: x86_64
2025-07-10 09:04:26 💻 Target environment: gnu
2025-07-10 09:04:26 💻 CPU: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
2025-07-10 09:04:26 💻 CPU cores: 12
2025-07-10 09:04:26 💻 Memory: 7946MB
2025-07-10 09:04:26 💻 Kernel: 6.4.16-linuxkit
2025-07-10 09:04:26 💻 Linux distribution: Debian GNU/Linux 12 (bookworm)
2025-07-10 09:04:26 💻 Virtual machine: yes
2025-07-10 09:04:26 📦 Highest known block at #0
2025-07-10 09:04:26 Running JSON-RPC server: addr=0.0.0.0:9944, allowed origins=["*"]
2025-07-10 09:04:26 🏁 CPU score: 1.14 GiBs
2025-07-10 09:04:26 〽️ Prometheus exporter started at 127.0.0.1:9615
2025-07-10 09:04:26 🏁 Memory score: 10.41 GiBs
2025-07-10 09:04:26 🏁 Disk score (seq. writes): 987.96 MiBs
2025-07-10 09:04:26 🏁 Disk score (rand. writes): 363.65 MiBs
2025-07-10 09:04:26 Development Service Ready
2025-07-10 09:04:26 💤 Idle (0 peers), best: #0 (0xa083…f354), finalized #0 (0xa083…f354), ⬇ 0 ⬆ 0
2025-07-10 09:04:26 💤 Idle (0 peers), best: #0 (0xa083…f354), finalized #0 (0xa083…f354), ⬇ 0 ⬆ 0
For more information on some of the flags and options used in the example, check out [Flags](#node-flags) and [Options](#node-options). If you want to see a complete list of all of the flags, options, and subcommands, open the help menu by running:
```bash
docker run --rm --name {{ networks.development.container_name }} \
moonbeamfoundation/moonbeam \
--help
```
To continue with the tutorial, the next section is not necessary, as you've already spun up a node with Docker. You can skip ahead to the [Configure your Moonbeam Development Node](#configure-moonbeam-dev-node) section.
### Spin Up a Node with a Binary File {: #getting-started-with-the-binary-file }
As an alternative to using Docker, you can spin up a node using the Moonbeam binary. This method is more time-consuming. Depending on your hardware, the process could take around 30 minutes to complete.
!!! note
If you know what you are doing, you can directly download the precompiled binaries attached to each release on the [Moonbeam release page](https://github.com/moonbeam-foundation/moonbeam/releases){target=\_blank}. These will not work in all systems. For example, the binaries only work with x86-64 Linux with specific versions of dependencies. The safest way to ensure compatibility is to compile the binary on the system where it will be run.
To build the binary file, you can take the following steps:
1. Clone a specific tag of the Moonbeam repo, which you can find on the [Moonbeam GitHub repository](https://github.com/moonbeam-foundation/moonbeam){target=\_blank}:
```bash
git clone -b {{ networks.development.build_tag }} https://github.com/moonbeam-foundation/moonbeam
cd moonbeam
```
!!! note
Spaces in the installation file path will cause a compilation error.
2. If you already have Rust installed, you can skip the next two steps. Otherwise, install Rust and its prerequisites [via Rust's recommended method](https://www.rust-lang.org/tools/install){target=\_blank} by executing:
```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```
3. Update your PATH environment variable by running:
```bash
source $HOME/.cargo/env
```
4. Build the development node by running:
!!! note
If you are using Ubuntu 20.04 or 22.04, then you will need to make sure these additional dependencies have been installed before building the binary:
```bash
apt install clang protobuf-compiler libprotobuf-dev pkg-config libssl-dev -y
```
For MacOS users, these dependencies can be installed via Homebrew:
```bash
brew install llvm
brew install protobuf
```
```bash
cargo build --release
```
Here is what the tail end of the build output should look like:
!!! note
The initial build will take a while. Depending on your hardware, you should expect approximately 30 minutes for the build process to finish.
Then, you will want to run the node in development mode using the following command:
```bash
./target/release/moonbeam --dev
```
!!! note
For people not familiar with Substrate, the `--dev` flag is a way to run a Substrate-based node in a single-node developer configuration for testing purposes. When you run your node with the `--dev` flag, your node is started in a fresh state, and its state does not persist.
You should see an output that looks like the following, showing an idle state waiting for blocks to be produced:
./target/release/moonbeam --dev 2025-07-10 09:04:26 Moonbeam Parachain Collator
2025-07-10 09:04:26 ✌️ version 0.46.0-d7df89e7161
2025-07-10 09:04:26 ❤️ by PureStake, 2019-2025
2025-07-10 09:04:26 📋 Chain specification: Moonbase Development Testnet
2025-07-10 09:04:26 🏷 Node name: black-and-white-sticks-9174
2025-07-10 09:04:26 👤 Role: AUTHORITY
2025-07-10 09:04:26 💾 Database: RocksDb at /tmp/substrateO3YeRz/chains/moonbase_dev/db/full
2025-07-10 09:04:26 🔨 Initializing Genesis block/state (state: 0x7c34…99c5, header-hash: 0xa083…f354)
2025-07-10 09:04:26 Using default protocol ID "sup" because none is configured in the chain specs
2025-07-10 09:04:26 🏷 Local node identity is: 12D3KooWLcpczme2JeBEfLqmjqkzYVKTGKhhGmwSzHjRXGBVhDX7
2025-07-10 09:04:26 💻 Operating system: linux
2025-07-10 09:04:26 💻 CPU architecture: x86_64
2025-07-10 09:04:26 💻 Target environment: gnu
2025-07-10 09:04:26 💻 CPU: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
2025-07-10 09:04:26 💻 CPU cores: 12
2025-07-10 09:04:26 💻 Memory: 7946MB
2025-07-10 09:04:26 💻 Kernel: 6.4.16-linuxkit
2025-07-10 09:04:26 💻 Linux distribution: Debian GNU/Linux 12 (bookworm)
2025-07-10 09:04:26 💻 Virtual machine: yes
2025-07-10 09:04:26 📦 Highest known block at #0
2025-07-10 09:04:26 Running JSON-RPC server: addr=0.0.0.0:9944, allowed origins=["*"]
2025-07-10 09:04:26 🏁 CPU score: 1.14 GiBs
2025-07-10 09:04:26 〽️ Prometheus exporter started at 127.0.0.1:9615
2025-07-10 09:04:26 🏁 Memory score: 10.41 GiBs
2025-07-10 09:04:26 🏁 Disk score (seq. writes): 987.96 MiBs
2025-07-10 09:04:26 🏁 Disk score (rand. writes): 363.65 MiBs
2025-07-10 09:04:26 Development Service Ready
2025-07-10 09:04:26 💤 Idle (0 peers), best: #0 (0xa083…f354), finalized #0 (0xa083…f354), ⬇ 0 ⬆ 0
2025-07-10 09:04:26 💤 Idle (0 peers), best: #0 (0xa083…f354), finalized #0 (0xa083…f354), ⬇ 0 ⬆ 0
For more information on some of the flags and options used in the example, check out the [Flags](#node-flags) and [Options](#node-options). If you want to see a complete list of all of the flags, options, and subcommands, open the help menu by running:
```bash
./target/release/moonbeam --help
```
## Configure Your Moonbeam Development Node {: #configure-moonbeam-dev-node }
Now that you know how to get a standard Moonbeam development node up and running, you may be wondering how you can configure it. The following sections will cover some common configurations you can use when you spin up your node.
### Common Flags to Configure Your Node {: #node-flags }
Flags do not take an argument. To use a flag, add it to the end of a command. For example:
```bash
./target/release/moonbeam --dev
```
- **`--dev`** - specifies the development chain
- **`--tmp`** - runs a temporary node in which all of the configuration will be deleted at the end of the process
- **`--rpc-external`** - listen to all RPC and WebSocket interfaces
### Common Options to Configure Your Node {: #node-options }
Options accept an argument to the right of the option. For example:
```bash
./target/release/moonbeam --dev --sealing 6000
```
- **`-l ` or `--log `** - sets a custom logging filter. The syntax for the log pattern is `=`. For example, to print all of the JSON-RPC logs, the command would look like this: `-l json=trace`
- **`--sealing `** - when blocks should be sealed in the dev service. Accepted arguments for interval: `instant`, `manual`, or a number representing the timer interval in milliseconds (for example, `6000` will have the node produce blocks every 6 seconds). The default is `instant``. Please refer to the [Configure Block Production](#configure-block-production) section below for more information
- **`--rpc-port `** - sets the unified port for HTTP and WS connections. Accepts a port as the argument. Default is {{ networks.parachain.rpc }}
- **`--ws-port `** - *deprecated as of [client v0.33.0](https://github.com/moonbeam-foundation/moonbeam/releases/tag/v0.33.0){target=\_blank}, use `--rpc-port` for HTTP and WS connections instead* - sets the WebSockets RPC server TCP port. As of [client v0.30.0](https://github.com/moonbeam-foundation/moonbeam/releases/tag/v0.30.0){target=\_blank}, it sets the unified port for both HTTP and WS connections. Accepts a port as the argument
- **`--rpc-max-connections `** - specifies the combined HTTP and WS connection limit. The default is 100 connections
- **`--ws-max-connections `** - *deprecated as of [client v0.33.0](https://github.com/moonbeam-foundation/moonbeam/releases/tag/v0.33.0){target=\_blank}, use `--rpc-max-connections` to limit the HTTP and WS connections instead* - this flag adjusts the combined HTTP and WS connection limit. The default is 100 connections
- **`--rpc-cors `** - specifies the browser origins allowed to access the HTTP and WS RPC servers. The origins can be a comma-separated list of the origins to allow access, or you can also specify `null`. When running a development node, the default is to allow all origins
For a complete list of flags and options, spin up your Moonbeam development node with `--help` added to the end of the command.
### Configure Block Production {: #configure-block-production }
By default, your Moonbeam development node is spun up in instant seal mode, which instantly authors blocks as transactions are received. However, you can specify when blocks should be authored or sealed by using the `--sealing` option.
The `--sealing` flag accepts any of the following arguments:
- `instant` - as we already covered, this is the default option in which blocks are authored as soon as a transaction is received
- `manual` - allows you to produce blocks manually. If a transaction is received, a block will not be produced until you manually create one
- an interval in milliseconds - authors a block on a specific time interval. For example, if you set it to `6000`, you will have the node produce blocks every 6 seconds
The flag should be appended to the start-up command in the following format:
```text
--sealing
```
If you choose `manual`, you'll need to manually create the blocks yourself, which can be done with the `engine_createBlock` JSON-RPC method:
```text
engine_createBlock(createEmpty: *bool*, finalize: *bool*, parentHash?: *BlockHash*)
```
For example, you can use the following snippet to manually create a block using [Ethers.js](/builders/ethereum/libraries/ethersjs/){target=\_blank}, an Ethereum library that makes it easy to interact with JSON-RPC methods:
```js
import { ethers } from 'ethers';
const produceBlock = async () => {
// Connect to the Ethereum node (if applicable, replace the URL with your node's address)
const provider = new ethers.JsonRpcProvider(
'{{ networks.development.rpc_url }}'
);
// Set the custom JSON-RPC method and parameters
const method = 'engine_createBlock';
const params = [true, true, null];
try {
// Send the custom JSON-RPC call
const result = await provider.send(method, params);
} catch (error) {
// Handle any errors that may occur
console.error('Error:', error.message);
}
};
produceBlock();
```
!!! note
If you're unfamiliar with Ethers, please refer to the [Ethers.js](/builders/ethereum/libraries/ethersjs/){target=\_blank} documentation page to learn more.
## Prefunded Development Accounts {: #pre-funded-development-accounts }
Moonbeam has a [unified accounts](/learn/core-concepts/unified-accounts/){target=\_blank} system, which enables users to have an Ethereum-styled H160 account that can interact with the Substrate API and the Ethereum API. As a result, you can interact with your account through [Polkadot.js Apps](/tokens/connect/polkadotjs/#connect-polkadotjs-apps){target=\_blank} or [MetaMask](/tokens/connect/metamask/){target=\_blank} (or any other [EVM wallet](/tokens/connect/){target=\_blank}). In addition, you can also use other [development tools](/builders/ethereum/dev-env/){target=\_blank}, such as [Remix](/builders/ethereum/dev-env/remix/){target=\_blank} and [Hardhat](/builders/ethereum/dev-env/hardhat/){target=\_blank}.
Your Moonbeam development node comes with ten prefunded Ethereum-styled accounts for development. The addresses are derived from Substrate's canonical development mnemonic:
```text
bottom drive obey lake curtain smoke basket hold race lonely fit walk
```
??? note "Development account addresses and private keys"
- Alith:
- Public Address: `0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac`
- Private Key: `0x5fb92d6e98884f76de468fa3f6278f8807c48bebc13595d45af5bdc4da702133`
- Baltathar:
- Public Address: `0x3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0`
- Private Key: `0x8075991ce870b93a8870eca0c0f91913d12f47948ca0fd25b49c6fa7cdbeee8b`
- Charleth:
- Public Address: `0x798d4Ba9baf0064Ec19eB4F0a1a45785ae9D6DFc`
- Private Key: `0x0b6e18cafb6ed99687ec547bd28139cafdd2bffe70e6b688025de6b445aa5c5b`
- Dorothy:
- Public Address: `0x773539d4Ac0e786233D90A233654ccEE26a613D9`
- Private Key: `0x39539ab1876910bbf3a223d84a29e28f1cb4e2e456503e7e91ed39b2e7223d68`
- Ethan:
- Public Address: `0xFf64d3F6efE2317EE2807d223a0Bdc4c0c49dfDB`
- Private Key: `0x7dce9bc8babb68fec1409be38c8e1a52650206a7ed90ff956ae8a6d15eeaaef4`
- Faith:
- Public Address: `0xC0F0f4ab324C46e55D02D0033343B4Be8A55532d`
- Private Key: `0xb9d2ea9a615f3165812e8d44de0d24da9bbd164b65c4f0573e1ce2c8dbd9c8df`
- Goliath:
- Public Address: `0x7BF369283338E12C90514468aa3868A551AB2929`
- Private Key: `0x96b8a38e12e1a31dee1eab2fffdf9d9990045f5b37e44d8cc27766ef294acf18`
- Heath:
- Public Address: `0x931f3600a299fd9B24cEfB3BfF79388D19804BeA`
- Private Key: `0x0d6dcaaef49272a5411896be8ad16c01c35d6f8c18873387b71fbc734759b0ab`
- Ida:
- Public Address: `0xC41C5F1123ECCd5ce233578B2e7ebd5693869d73`
- Private Key: `0x4c42532034540267bf568198ccec4cb822a025da542861fcb146a5fab6433ff8`
- Judith:
- Public Address: `0x2898FE7a42Be376C8BC7AF536A940F7Fd5aDd423`
- Private Key: `0x94c49300a58d576011096bcb006aa06f5a91b34b4383891e8029c21dc39fbb8b`
Also included with the development node is an additional prefunded account used for testing purposes:
- Gerald:
- Public Address: `0x6Be02d1d3665660d22FF9624b7BE0551ee1Ac91b`
- Private Key: `0x99b3c12287537e38c90a9219d4cb074a89a16e9cdb20bf85728ebd97c343e342`
You can connect any of these accounts to [MetaMask](/tokens/connect/metamask/){target=\_blank}, [Talisman](/tokens/connect/talisman/){target=\_blank}, [Polkadot.js Apps](/tokens/connect/polkadotjs/){target=\_blank}, etc., using their private keys.
## Development Node Endpoints {: #access-your-development-node }
You can access your Moonbeam development node using the following RPC and WSS endpoints:
=== "HTTP"
```text
{{ networks.development.rpc_url }}
```
=== "WSS"
```text
{{ networks.development.wss_url }}
```
## Block Explorers {: #block-explorers }
For a Moonbeam development node, you can use any of the following block explorers:
- **Substrate API** — [Polkadot.js Apps](https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:9944#/explorer){target=\_blank} on WS port `{{ networks.parachain.ws }}`
- **Ethereum API JSON-RPC-based** — [Moonbeam Basic Explorer](https://moonbeam-explorer.netlify.app/?network=MoonbeamDevNode){target=\_blank} on HTTP port `{{ networks.parachain.ws }}`
## Debug, Trace, and TxPool APIs {: #debug-trace-txpool-apis }
You can also gain access to some non-standard RPC methods by running a tracing node, which allows developers to inspect and debug transactions during runtime. Tracing nodes use a different Docker image than a standard Moonbeam development node.
To learn how to run a Moonbeam development tracing node, check out the [Run a Tracing Node](/node-operators/networks/tracing-node/){target=\_blank} guide, and be sure to switch to the **Moonbeam Development Node** tab throughout the instructions. Then, to access the non-standard RPC methods with your tracing node, check out the [Debug & Trace](/builders/ethereum/json-rpc/debug-trace/){target=\_blank} guide.
## Purge a Development Node {: #purging-your-node }
If you want to remove data associated with your node, you can purge it. The instructions for purging a node are different depending on how you initially spun up your node.
### Purge a Node Spun Up with Docker {: #purge-docker-node }
If you spun up your node using Docker along with the `-v` flag to specify a mounted directory for your container, you will need to purge that directory. To do so, you can run the following command:
```bash
sudo rm -rf {{ networks.moonbase.node_directory }}/*
```
If you followed the instructions in this guide and did not use the `-v` flag, you can stop and remove the Docker container. The associated data will be removed along with it. To do so, you can run the following command:
```bash
sudo docker stop `CONTAINER_ID` && docker rm `CONTAINER_ID`
```
### Purge a Node Spun up with a Binary File {: #purge-binary-node }
When running a node via the binary file, data is stored in a local directory, typically located in `~/.local/shared/moonbeam/chains/development/db`. If you want to start a fresh instance of the node, you can either delete the content of the folder or run the following command inside the `moonbeam` folder:
```bash
./target/release/moonbeam purge-chain --dev -y
```
This will remove the data folder. Note that all chain data is now lost. To learn more about all of the available `purge-chain` commands, you can check out the [Purging Binary Data](/node-operators/networks/run-a-node/systemd/#purging-compiled-binary){target=\_blank} section of our documentation.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/get-started/networks/moonbeam/
--- BEGIN CONTENT ---
---
title: Get Started with Moonbeam
description: Learn how to connect to Moonbeam via RPC and WSS endpoints, how to connect MetaMask to Moonbeam, and about the available Moonbeam block explorers.
categories: Basics
---
# Get Started with Moonbeam
## Network Endpoints {: #network-endpoints }
Moonbeam has two types of endpoints available for users to connect to: one for HTTPS and one for WSS.
If you're looking for your own endpoints suitable for production use, you can check out the [Endpoint Providers](/builders/get-started/endpoints/#endpoint-providers){target=\_blank} section of our documentation. Otherwise, to get started quickly you can use one of the following public HTTPS or WSS endpoints:
=== "HTTPS"
| Provider | RPC URL | Limits |
|:-----------:|:------------------------------------------------------------------:|:-----------:|
| Dwellir |
| 10k req/day |
## Quick Start {: #quick-start }
Before getting started, make sure you've retrieved your own endpoint and API key from one of the custom [Endpoint Providers](/builders/get-started/endpoints/){target=\_blank}. Then for the [Web3.js library](/builders/ethereum/libraries/web3js/){target=\_blank}, you can create a local Web3 instance and set the provider to connect to Moonbeam (both HTTP and WS are supported):
```js
const { Web3 } = require('web3'); // Load Web3 library
.
.
.
// Create local Web3 instance - set Moonbeam as provider
const web3 = new Web3('INSERT_RPC_API_ENDPOINT'); // Insert your RPC URL here
```
For the [Ethers.js library](/builders/ethereum/libraries/ethersjs/){target=\_blank}, define the provider by using `ethers.JsonRpcProvider(providerURL, {object})` and setting the provider URL to Moonbeam:
```js
const ethers = require('ethers'); // Load Ethers library
const providerURL = 'INSERT_RPC_API_ENDPOINT'; // Insert your RPC URL here
// Define provider
const provider = new ethers.JsonRpcProvider(providerURL, {
chainId: 1284,
name: 'moonbeam'
});
```
Any Ethereum wallet should be able to generate a valid address for Moonbeam (for example, [MetaMask](https://metamask.io){target=\_blank}).
## Chain ID {: #chain-id }
Moonbeam chain ID is: `1284`, or `0x504` in hex.
## Block Explorers {: #block-explorers }
For Moonbeam, you can use any of the following block explorers:
- **Ethereum API (Etherscan Equivalent)** — [Moonscan](https://moonbeam.moonscan.io){target=\_blank}
- **Ethereum API JSON-RPC based** — [Moonbeam Basic Explorer](https://moonbeam-explorer.netlify.app/?network=Moonbeam){target=\_blank}
- **Substrate API** — [Subscan](https://moonbeam.subscan.io){target=\_blank} or [Polkadot.js Apps](https://polkadot.js.org/apps/?rpc=wss://wss.api.moonbeam.network#/explorer){target=\_blank}
For more information on each of the available block explorers, please head to the [Block Explorers](/builders/get-started/explorers/){target=\_blank} section of the documentation.
## Connect MetaMask {: #connect-metamask }
If you already have MetaMask installed, you can easily connect MetaMask to Moonbeam:
!!! note
MetaMask will popup asking for permission to add Moonbeam as a custom network. Once you approve permissions, MetaMask will switch your current network to Moonbeam.
If you do not have MetaMask installed, or would like to follow a tutorial to get started, please check out the [Interacting with Moonbeam using MetaMask](/tokens/connect/metamask/){target=\_blank} guide.
## Configuration {: #configuration }
Please note the following gas configuration parameters. These values are subject to change in future runtime upgrades.
| Variable | Value |
|:---------------------:|:------------------------------------------:|
| Minimum gas price | {{ networks.moonbeam.min_gas_price }} Gwei |
| Target block time | {{ networks.moonbeam.block_time }} seconds |
| Block gas limit | {{ networks.moonbeam.gas_block }} |
| Transaction gas limit | {{ networks.moonbeam.gas_tx }} |
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/get-started/networks/moonriver/
--- BEGIN CONTENT ---
---
title: Moonriver Get Started Guide
description: Learn how to connect to Moonriver via RPC and WSS endpoints, how to connect MetaMask to Moonriver, and about the available Moonriver block explorers.
categories: Basics
---
# Get Started with Moonriver
## Network Endpoints {: #network-endpoints }
Moonriver has two types of endpoints available for users to connect to: one for HTTPS and one for WSS.
If you're looking for your own endpoints suitable for production use, you can check out the [Endpoint Providers](/builders/get-started/endpoints/#endpoint-providers){target=\_blank} section of our documentation. Otherwise, to get started quickly you can use one of the following public HTTPS or WSS endpoints:
=== "HTTPS"
| Provider | RPC URL | Limits |
|:-----------:|:-------------------------------------------------------------------:|:-----------:|
| Dwellir |
| 200 req/sec |
## Quick Start {: #quick-start }
Before getting started, make sure you've retrieved your own endpoint and API key from one of the custom [Endpoint Providers](/builders/get-started/endpoints/){target=\_blank}. Then for the [Web3.js library](/builders/ethereum/libraries/web3js/){target=\_blank}, you can create a local Web3 instance and set the provider to connect to Moonriver (both HTTP and WS are supported):
```js
const { Web3 } = require('web3'); // Load Web3 library
.
.
.
// Create local Web3 instance - set Moonriver as provider
const web3 = new Web3('INSERT_RPC_API_ENDPOINT'); // Insert your RPC URL here
```
For the [Ethers.js library](/builders/ethereum/libraries/ethersjs/){target=\_blank}, define the provider by using `ethers.JsonRpcProvider(providerURL, {object})` and setting the provider URL to Moonriver:
```js
const ethers = require('ethers'); // Load Ethers library
const providerURL = 'INSERT_RPC_API_ENDPOINT'; // Insert your RPC URL here
// Define provider
const provider = new ethers.JsonRpcProvider(providerURL, {
chainId: 1285,
name: 'moonriver'
});
```
Any Ethereum wallet should be able to generate a valid address for Moonbeam (for example, [MetaMask](https://metamask.io){target=\_blank}).
## Chain ID {: #chain-id }
Moonriver chain ID is: `1285`, or `0x505` in hex.
## Block Explorers {: #block-explorers }
For Moonriver, you can use any of the following block explorers:
- **Ethereum API (Etherscan Equivalent)** — [Moonscan](https://moonriver.moonscan.io){target=\_blank}
- **Ethereum API JSON-RPC based** — [Moonbeam Basic Explorer](https://moonbeam-explorer.netlify.app/?network=Moonriver){target=\_blank}
- **Substrate API** — [Subscan](https://moonriver.subscan.io){target=\_blank} or [Polkadot.js Apps](https://polkadot.js.org/apps/?rpc=wss://wss.api.moonriver.moonbeam.network#/explorer){target=\_blank}
For more information on each of the available block explorers, please head to the [Block Explorers](/builders/get-started/explorers/) section of the documentation.
## Connect MetaMask {: #connect-metamask }
If you already have MetaMask installed, you can easily connect MetaMask to Moonriver:
!!! note
MetaMask will popup asking for permission to add Moonriver as a custom network. Once you approve permissions, MetaMask will switch your current network to Moonriver.
If you do not have MetaMask installed, or would like to follow a tutorial to get started, please check out the [Interacting with Moonbeam using MetaMask](/tokens/connect/metamask/) guide.
## Configuration {: #configuration }
Please note the following gas configuration parameters. These values are subject to change in future runtime upgrades.
| Variable | Value |
|:---------------------:|:-------------------------------------------:|
| Minimum gas price | {{ networks.moonriver.min_gas_price }} Gwei |
| Target block time | {{ networks.moonriver.block_time }} seconds |
| Block gas limit | {{ networks.moonriver.gas_block }} |
| Transaction gas limit | {{ networks.moonriver.gas_tx }} |
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/get-started/quick-start/
--- BEGIN CONTENT ---
---
title: Quickly Get Started
description: Everything you need to know to get started developing, deploying, and interacting with smart contracts on Moonbeam.
categories: Basics
---
# Quick Start Guide for Developing on Moonbeam
## Quick Overview {: #overview }
Moonbeam is a fully Ethereum-compatible smart contract platform on Polkadot. As such, you can interact with Moonbeam via the [Ethereum API](/builders/ethereum/){target=\_blank} and [Substrate API](/builders/substrate/){target=\_blank}.
Although Moonbeam is a Substrate-based platform, Moonbeam uses a [unified accounts](/learn/core-concepts/unified-accounts/){target=\_blank} system, which replaces Substrate-style accounts and keys with Ethereum-style accounts and keys. As a result, you can interact with your Moonbeam account with [MetaMask](/tokens/connect/metamask/){target=\_blank}, [Ledger](/tokens/connect/ledger/){target=\_blank}, and other Ethereum-compatible wallets by simply adding Moonbeam's network configurations. Similarly, you can develop on Moonbeam using Ethereum [libraries](/builders/ethereum/libraries/){target=\_blank} and [development environments](/builders/ethereum/dev-env/){target=\_blank}.
## Moonbeam Networks {: #moonbeam-networks }
To get started developing on Moonbeam, it's important to be aware of the various networks within the Moonbeam ecosystem.
| Network | Network Type | Relay Chain | Native Asset Symbol | Native Asset Decimals |
|:-----------------------------------------------------------------------------------------:|:-------------:|:--------------------------------------------------------------------------------:|:-------------------:|:---------------------:|
| [Moonbeam](/builders/get-started/networks/moonbeam/){target=\_blank} | MainNet | [Polkadot](https://polkadot.com){target=\_blank} | GLMR | 18 |
| [Moonriver](/builders/get-started/networks/moonriver/){target=\_blank} | MainNet | [Kusama](https://kusama.network){target=\_blank} | MOVR | 18 |
| [Moonbase Alpha](/builders/get-started/networks/moonbase/){target=\_blank} | TestNet | [Alphanet relay](/learn/platform/networks/moonbase/#relay-chain){target=\_blank} | DEV | 18 |
| [Moonbeam Development Node](/builders/get-started/networks/moonbeam-dev/){target=\_blank} | Local TestNet | None | DEV | 18 |
!!! note
A Moonbeam development node doesn't have a relay chain as its purpose is to be your own personal development environment where you can get started developing quickly without the overhead of a relay chain.
### Network Configurations {: #network-configurations }
When working with developer tools, depending on the tool, you might need to configure Moonbeam to interact with the network. To do so, you can use the following information:
=== "Moonbeam"
| Variable | Value |
|:---------------:|:------------------------------------------------------------------------------------------------------:|
| Chain ID |
```{{ networks.moonbeam.chain_id }}```
|
| Public RPC URLs |
```https://moonbeam.public.blastapi.io```
```https://moonbeam.unitedbloc.com```
|
| Public WSS URLs |
```wss://moonbeam.public.blastapi.io```
|
=== "Moonriver"
| Variable | Value |
|:---------------:|:--------------------------------------------------------------------------------------------------------:|
| Chain ID |
```{{ networks.moonriver.chain_id }}```
|
| Public RPC URLs |
```https://moonriver.public.blastapi.io```
```https://moonriver.unitedbloc.com```
|
| Public WSS URLs |
```wss://moonriver.public.blastapi.io```
|
=== "Moonbase Alpha"
| Variable | Value |
|:---------------:|:-----------------------------------------------------------------------------------------------------------:|
| Chain ID |
```{{ networks.moonbase.chain_id }}```
|
| Public RPC URLs |
```https://moonbase-alpha.public.blastapi.io```
```{{ networks.moonbase.rpc_url }}```
|
| Public WSS URLs |
```wss://moonbase-alpha.public.blastapi.io```
```{{ networks.moonbase.wss_url }}```
|
=== "Moonbeam Dev Node"
| Variable | Value |
|:-------------:|:----------------------------------------------------:|
| Chain ID |
```{{ networks.development.chain_id }}```
|
| Local RPC URL |
```{{ networks.development.rpc_url }}```
|
| Local WSS URL |
```{{ networks.development.wss_url }}```
|
!!! note
You can create your own endpoint suitable for development or production from one of the [supported RPC providers](/builders/get-started/endpoints/#endpoint-providers){target=\_blank}.
### Block Explorers {: #explorers }
Moonbeam provides two different kinds of explorers: ones to query the Ethereum API, and others dedicated to the Substrate API. All EVM-based transactions are accessible via the Ethereum API whereas the Substrate API can be relied upon for Substrate-native functions such as governance, staking, and some information about EVM-based transactions. For more information on each explorer, please check out the [Block Explorers](/builders/get-started/explorers/){target=\_blank} page.
=== "Moonbeam"
| Block Explorer | Type | URL |
|:--------------:|:---------:|:-------------------------------------------------------------------------------------------------------------------------------------:|
| Moonscan | EVM | [https://moonbeam.moonscan.io/](https://moonbeam.moonscan.io){target=\_blank} |
| Expedition | EVM | [https://moonbeam-explorer.netlify.app/?network=Moonbeam](https://moonbeam-explorer.netlify.app/?network=Moonbeam){target=\_blank} |
| Subscan | Substrate | [https://moonbeam.subscan.io/](https://moonbeam.subscan.io){target=\_blank} |
| Polkadot.js | Substrate | [https://polkadot.js.org/apps/#/explorer](https://polkadot.js.org/apps/?rpc=wss://wss.api.moonbeam.network#/explorer){target=\_blank} |
=== "Moonriver"
| Block Explorer | Type | URL |
|:--------------:|:---------:|:-----------------------------------------------------------------------------------------------------------------------------------------------:|
| Moonscan | EVM | [https://moonriver.moonscan.io/](https://moonriver.moonscan.io){target=\_blank} |
| Expedition | EVM | [https://moonbeam-explorer.netlify.app/?network=Moonriver](https://moonbeam-explorer.netlify.app/?network=Moonriver){target=\_blank} |
| Subscan | Substrate | [https://moonriver.subscan.io/](https://moonriver.subscan.io){target=\_blank} |
| Polkadot.js | Substrate | [https://polkadot.js.org/apps/#/explorer](https://polkadot.js.org/apps/?rpc=wss://wss.api.moonrvier.moonbeam.network#/explorer){target=\_blank} |
=== "Moonbase Alpha"
| Block Explorer | Type | URL |
|:--------------:|:---------:|:----------------------------------------------------------------------------------------------------------------------------------------------:|
| Moonscan | EVM | [https://moonbase.moonscan.io/](https://moonbase.moonscan.io){target=\_blank} |
| Expedition | EVM | [https://moonbeam-explorer.netlify.app/?network=MoonbaseAlpha](https://moonbeam-explorer.netlify.app/?network=MoonbaseAlpha){target=\_blank} |
| Subscan | Substrate | [https://moonbase.subscan.io/](https://moonbase.subscan.io){target=\_blank} |
| Polkadot.js | Substrate | [https://polkadot.js.org/apps/#/explorer](https://polkadot.js.org/apps/?rpc=wss://wss.api.moonbase.moonbeam.network#/explorer){target=\_blank} |
=== "Moonbeam Dev Node"
| Block Explorer | Type | URL |
|:--------------:|:---------:|:-------------------------------------------------------------------------------------------------------------------------------------------------:|
| Expedition | EVM | [https://moonbeam-explorer.netlify.app/?network=MoonbeamDevNode](https://moonbeam-explorer.netlify.app/?network=MoonbeamDevNode){target=\_blank} |
| Polkadot.js | Substrate | [https://polkadot.js.org/apps/#/explorer](https://polkadot.js.org/apps/?rpc=wss://ws%3A%2F%2F127.0.0.1%3A9944#/explorer){target=\_blank} |
## Funding TestNet Accounts {: #testnet-tokens }
To get started developing on one of the TestNets, you'll need to fund your account with DEV tokens to send transactions. Please note that DEV tokens have no real value and are for testing purposes only.
| TestNet | Where To Get Tokens From |
|:-----------------------------------------------------------------------------------------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
| [Moonbase Alpha](/builders/get-started/networks/moonbase/){target=\_blank} | The [Moonbase Alpha Faucet](https://faucet.moonbeam.network){target=\_blank} website. The faucet dispenses {{ networks.moonbase.website_faucet_amount }} every 24 hours |
| [Moonbeam Development Node](/builders/get-started/networks/moonbeam-dev/){target=\_blank} | Any of the [ten pre-funded accounts](/builders/get-started/networks/moonbeam-dev/#pre-funded-development-accounts){target=\_blank} that come with your development node |
## Development Tools {: #development-tools }
As Moonbeam is a Substrate-based chain that is fully Ethereum-compatible, you can use Substrate-based tools and Ethereum-based tools.
### JavaScript Tools {: #javascript }
=== "Ethereum"
| Tool | Type |
|:------------------------------------------------------------------------:|:---------------:|
| [Ethers.js](/builders/ethereum/libraries/ethersjs/){target=\_blank} | Library |
| [Web3.js](/builders/ethereum/libraries/web3js/){target=\_blank} | Library |
| [Hardhat](/builders/ethereum/dev-env/hardhat/){target=\_blank} | Dev Environment |
| [OpenZeppelin](/builders/ethereum/dev-env/openzeppelin/){target=\_blank} | Dev Environment |
| [Remix](/builders/ethereum/dev-env/remix/){target=\_blank} | Dev Environment |
| [Scaffold-Eth](/builders/ethereum/dev-env/scaffold-eth/){target=\_blank} | Dev Environment |
| [thirdweb](/builders/ethereum/dev-env/thirdweb/){target=\_blank} | Dev Environment |
| [Waffle & Mars](/builders/ethereum/dev-env/waffle-mars/){target=\_blank} | Dev Environment |
=== "Substrate"
| Tool | Type |
|:---------------------------------------------------------------------------------:|:-------:|
| [Polkadot.js API](/builders/substrate/libraries/polkadot-js-api/){target=\_blank} | Library |
### Python Tools {: #python }
=== "Ethereum"
| Tool | Type |
|:---------------------------------------------------------------:|:---------------:|
| [Web3.py](/builders/ethereum/libraries/web3py/){target=\_blank} | Library |
| [Ape](/builders/ethereum/dev-env/ape/){target=\_blank} | Dev Environment |
=== "Substrate"
| Tool | Type |
|:-----------------------------------------------------------------------------------------------:|:-------:|
| [Py Substrate Interface](/builders/substrate/libraries/py-substrate-interface/){target=\_blank} | Library |
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/interoperability/xcm/core-concepts/instructions/
--- BEGIN CONTENT ---
---
title: XCM Instructions
description: When XCM instructions are combined, they form an XCM message that performs a cross-chain action. Take a look at some of the most common instructions.
categories: XCM, Basics
---
# XCM Instructions
## Introduction {: #introduction }
XCM messages contain a series of [actions and instructions](https://github.com/paritytech/xcm-format#5-the-xcvm-instruction-set){target=\_blank} that are executed by the Cross-Consensus Virtual Machine (XCVM). An action (for example, transferring a token from one blockchain to another) consists of instructions that the XCVM partly executes in the origin and destination chains.
For example, an XCM message that transfers DOT from Polkadot to Moonbeam will include the following XCM instructions (in that order), some of which are executed on Polkadot and some of which are executed on Moonbeam:
1. [TransferReserveAsset](#transfer-reserve-asset) — executed in Polkadot
2. [ReserveAssetDeposited](#reserve-asset-deposited) — executed in Moonbeam
3. [ClearOrigin](#clear-origin) — executed in Moonbeam
4. [BuyExecution](#buy-execution) — executed in Moonbeam
5. [DepositAsset](#deposit-asset) — executed in Moonbeam
Building the instructions for an XCM message from scratch is not an easy task. Consequently, there are wrapper functions and pallets that developers can leverage to use XCM features. The [Polkadot XCM](/builders/interoperability/xcm/xc20/send-xc20s/xcm-pallet/){target=\_blank} and [XCM Transactor](/builders/interoperability/xcm/remote-execution/substrate-calls/xcm-transactor-pallet/){target=\_blank} Pallets provide functions with a predefined set of XCM instructions to either send [XC-20s](/builders/interoperability/xcm/xc20/overview/){target=\_blank} or remotely execute on other chains via XCM.
If you're interested in experimenting with different combinations of instructions, you can [use the Polkadot XCM Pallet to execute and send custom XCM messages](/builders/interoperability/xcm/send-execute-xcm/){target=\_blank}.
This guide provides an overview of some of the most commonly used XCM instructions, including those in the above example.
## Buy Execution {: #buy-execution }
The [`BuyExecution`](https://github.com/paritytech/xcm-format#buyexecution){target=\_blank} instruction typically gets executed in the target chain. It takes assets from the holding register, a temporary position in the Cross-Consensus Virtual Machine (XCVM), to pay for execution fees. The target chain determines the fees to pay.
## Clear Origin {: #clear-origin }
The [`ClearOrigin`](https://github.com/paritytech/xcm-format#clearorigin){target=\_blank} instruction gets executed in the target chain. It clears the origin of the XCM author, thereby ensuring that later XCM instructions cannot command the authority of the author.
## Deposit Asset {: #deposit-asset }
The [`DepositAsset`](https://github.com/paritytech/xcm-format#depositasset){target=\_blank} instruction gets executed in the target chain. It removes the assets from the holding register, a temporary position in the Cross-Consensus Virtual Machine (XCVM), and sends them to a destination account on the target chain.
## Descend Origin {: #descend-origin }
The [`DescendOrigin`](https://github.com/paritytech/xcm-format#descendorigin){target=\_blank} instruction gets executed in the target chain. It mutates the origin on the target chain to match the origin on the source chain, ensuring execution on the target chain occurs on behalf of the same entity initiating the XCM message on the source chain.
## Initiate Reserve Withdraw {: #initiate-reserve-withdraw }
The [`InitiateReserveWithdraw`](https://github.com/paritytech/xcm-format#initiatereservewithdraw){target=\_blank} instruction gets executed in the source chain. It removes the assets from the holding register, a temporary position in the Cross-Consensus Virtual Machine (XCVM), (essentially burning them), and sends an XCM message to the reserve chain starting with the `WithdrawAsset` instruction.
## Refund Surplus {: #refund-surplus }
The [`RefundSurplus`](https://github.com/paritytech/xcm-format#refundsurplus){target=\_blank} instruction typically gets executed in the target chain after the XCM is processed. This instruction will take any leftover assets from the `BuyExecution` instruction and put the assets into the holding register, a temporary position in the Cross-Consensus Virtual Machine (XCVM).
## Reserve Asset Deposited {: #reserve-asset-deposited }
The [`ReserveAssetDeposited`](https://github.com/paritytech/xcm-format#reserveassetdeposited-){target=\_blank} instruction gets executed in the target chain. It takes a representation of the assets received in the Sovereign account and places them into the holding register, a temporary position in the Cross-Consensus Virtual Machine (XCVM).
## Set Appendix {: #set-appendix }
The [`SetAppendix`](https://github.com/paritytech/xcm-format#setappendix){target=\_blank} instruction gets executed in the target chain. It sets the appendix register, which holds code that should be run after the current execution is finished.
## Transfer Reserve Asset {: #transfer-reserve-asset }
The [`TransferReserveAsset`](https://github.com/paritytech/xcm-format#transferreserveasset){target=\_blank} instruction gets executed in the reserve chain. It moves assets from the origin account and deposits them into a destination account on the target chain. It then sends an XCM message to the target chain with the `ReserveAssetDeposited` instruction, followed by the XCM instructions that are to be executed.
## Transact {: #transact }
The [`Transact`](https://github.com/paritytech/xcm-format#transact){target=\_blank} instruction gets executed in the target chain. It dispatches encoded call data from a given origin, allowing for the execution of specific operations or functions on the target chain.
## Withdraw Asset {: #withdraw-asset }
The [`WithdrawAsset`](https://github.com/paritytech/xcm-format#withdrawasset){target=\_blank} instruction can be executed in either the source or target chain. It removes assets and places them into the holding register, a temporary position in the Cross-Consensus Virtual Machine (XCVM).
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/interoperability/xcm/overview/
--- BEGIN CONTENT ---
---
title: Cross-Consensus Messaging (XCM)
description: An overview of how cross-consensus messaging (XCM) works and how developers can leverage Polkadot/Kusama XCM to gain access to new assets.
categories: Basics, XCM
---
# Cross-Consensus Messaging (XCM)
## Introduction {: #introduction }
[Polkadot's architecture](https://wiki.polkadot.com/learn/learn-architecture/){target=\_blank} allows parachains to natively interoperate with each other, enabling cross-blockchain transfers of any type of data or asset.
To do so, a [Cross-Consensus Message (XCM)](https://wiki.polkadot.com/learn/learn-xcm/){target=\_blank} format defines a language around how the message transfer between two interoperating blockchains should be performed. XCM is not specific to Polkadot, as it aims to be a generic and extensible language between different consensus systems.
This page is a brief introduction and overview of XCM and other related elements. More information can be found in [Polkadot's Wiki](https://wiki.polkadot.com/learn/learn-xcm/){target=\_blank}.
If you want to jump to more XCM-related content, feel free to check out the following pages:
- [**Core XCM Concepts**](/builders/interoperability/xcm/core-concepts/){target=\_blank} - learn topics related to [XCM Instructions](/builders/interoperability/xcm/core-concepts/instructions/){target=\_blank}, [Multilocations](/builders/interoperability/xcm/core-concepts/multilocations/){target=\_blank}, and [XCM Fees](/builders/interoperability/xcm/core-concepts/weights-fees/){target=\_blank}
- [**XC Registration**](/builders/interoperability/xcm/xc-registration/){target=\_blank} - go through the process of [Opening an XCM Channel with Moonbeam](/builders/interoperability/xcm/xc-registration/xc-integration/){target=\_blank} and how to [Register Polkadot Native Assets as XC-20s](/builders/interoperability/xcm/xc-registration/assets/){target=\_blank}
- [**XC-20s**](/builders/interoperability/xcm/xc20/){target=\_blank} - read an [Overview](/builders/interoperability/xcm/xc20/overview/){target=\_blank} of this Moonbeam-only asset class and learn how to [Interact with XC-20s](/builders/interoperability/xcm/xc20/interact/){target=\_blank} and how to [Send them via XCM](/builders/interoperability/xcm/xc20/send-xc20s/){target=\_blank}
- [**Remote Execution via XCM**](/builders/interoperability/xcm/remote-execution/){target=\_blank} - grasp all concepts related to remote execution via XCM, starting with a [High-Level Overview](/builders/interoperability/xcm/remote-execution/overview/){target=\_blank}, then [Computed Origins](/builders/interoperability/xcm/remote-execution/computed-origins/){target=\_blank} and wrapping up with [Remote Calls via XCM](/builders/interoperability/xcm/remote-execution/substrate-calls/){target=\_blank} and [Remote EVM Calls via XCM](/builders/interoperability/xcm/remote-execution/remote-evm-calls/){target=\_blank}
- [**XCM SDK**](https://moonbeam-foundation.github.io/xcm-sdk/latest/){target=\_blank} - learn how to [Use Moonbeam's XCM SDK](https://moonbeam-foundation.github.io/xcm-sdk/latest/example-usage/xcm/){target=\_blank}
- **XCM Debugging and Tools** - learn how to test some XCM scenarios by [Sending and Executing Generic XCM Messages](/builders/interoperability/xcm/send-execute-xcm/){target=\_blank}, or how to use the [XCM Utilities Precompile](/builders/interoperability/xcm/xcm-utils/){target=\_blank} to access XCM_related utility functions directly within the EVM
## General XCM Definitions {: #general-xcm-definitions }
- **XCM** — stands for Cross-Consensus Message. It is a general way for consensus systems to communicate with each other
- **VMP** — stands for Vertical Message Passing, one of the transport methods for XCMs. It allows parachains to exchange messages with the relay chain. *UMP* (Upward Message Passing) enables parachains to send messages to their relay chain, while *DMP* (Downward Message Passing) enables the relay chain to pass messages down to one of their parachains
- **XCMP** — stands for Cross-Consensus Message Passing, one of the transport methods for XCMs. It allows parachains to exchange messages with other parachains on the same relay chain
- **HRMP** — stands for Horizontal Relay-routed Message Passing, a stop-gap protocol while a full XCMP implementation is launched. It has the same interface as XCMP, but messages are stored on the relay chain
- **Sovereign account** — an account each chain in the ecosystem has, one for the relay chain and the other for other parachains. It is calculated as the `blake2` hash of a specific word and parachain ID concatenated (`blake2(para+ParachainID)` for the Sovereign account in the relay chain, and `blake2(sibl+ParachainID)` for the Sovereign account in other parachains), truncating the hash to the correct length. The account is owned by root and can only be used through SUDO (if available) or [governance (referenda)](/learn/features/governance/){target=\_blank}. The Sovereign account typically signs XCM messages in other chains in the ecosystem
- **Multilocation** — a way to specify a point in the entire relay chain/parachain ecosystem relative to a given origin. For example, it can be used to specify a specific parachain, asset, account, or even a pallet inside a parachain. In general terms, a multilocation is defined with a `parents` and an `interior`:
- `parents` - refers to how many "hops" into a parent blockchain you need to take from a given origin
- `interior` - refers to how many fields you need to define the target point.
For example, to target a parachain with ID `1000` from another parachain, the multilocation would be `{ "parents": 1, "interior": { "X1": [{ "Parachain": 1000 }]}}`
## Cross-Chain Transport Protocols via XCM {: #xcm-transport-protocols }
XCM implements two cross-consensus or transport protocols for acting on XCM messages between its constituent parachains, Moonbeam being one of them:
- **Vertical Message Passing (VMP)** — once a project is onboarded as a parachain, it automatically has a bi-directional communication channel with the relay chain. Therefore, there is no need for chain registration. VMP is divided into two kinds of message-passing transport protocols:
* **Upward Message Passing (UMP)** — allows parachains to send messages to their relay chain, for example, from Moonbeam to Polkadot
* **Downward Message Passing (DMP)** — allows the relay chain to pass messages down to one of their parachains, for example, from Polkadot to Moonbeam
- **Cross-Chain Message Passing (XCMP)** — allows two parachains to exchange messages as long as they are connected to the same relay chain. Cross-chain transactions are resolved using a simple queuing mechanism based on a Merkle tree to ensure fidelity. Collators exchange messages between parachains, while the relay chain validators will verify that the message transmission happened
!!! note
Currently, while XCMP is being developed, a stop-gap protocol is implemented called Horizontal Relay-routed Message Passing (HRMP), in which the messages are stored in and read from the relay chain. This will be deprecated in the future for the full XCMP implementation.

## Establishing Cross-Chain Communication {: #channel-registration }
Before two chains can start communicating, a messaging channel must be opened. Channels are unidirectional, meaning that a channel from chain A to chain B will only pass messages from A to B. Therefore, two channels must be opened to send messages back and forth.
A channel for XCMs between the relay chain and parachain is automatically opened when a connection is established. However, when parachain A wants to open a communication channel with parachain B, parachain A must send an open channel extrinsic to its network. This extrinsic is an XCM as well!
Even though parachain A has expressed its intentions of opening an XCM channel with parachain B, the latter has not signaled to the relay chain its intentions to receive messages from parachain A. Therefore, to have an established channel, parachain B must send an extrinsic (an XCM) to the relay chain. The accepting channel extrinsic is similar to the previous one. However, the encoded call data only includes the new method (accept channel) and the parachain ID of the sender (parachain A in this example). Once both parachains have agreed, the channel is opened within the following epoch.
To learn more about the channel registration process, please refer to the [How to Establish an XC Integration with Moonbeam](/builders/interoperability/xcm/xc-registration/xc-integration/){target=\_blank} guide.

Once the channel is established, cross-chain messages can be sent between parachains. For asset transfers, assets need to be registered before being transferred through XCMs, either by being baked into the runtime as a constant or through a pallet. Moonbeam relies on a Substrate pallet to handle asset registration without the need for runtime upgrades, making the process a lot simpler.
To learn how to register an asset on Moonbeam and the information necessary to add Moonbeam assets to another chain, please refer to the [How to Register Cross-Chain Assets](/builders/interoperability/xcm/xc-registration/assets/){target=\_blank} guide.
## XCM on Moonbeam {: #moonbeam-and-xcm }
As Moonbeam is a parachain within the Polkadot ecosystems, one of the most direct implementations of XCM is to enable asset transfer from Polkadot and other parachains from/to Moonbeam. This allows users to bring their tokens to Moonbeam and all its dApps.
To this end, Moonbeam has introduced [XC-20s](/builders/interoperability/xcm/xc20/overview/){target=\_blank}, which expand on Moonbeam's unique Ethereum compatibility features. XC-20s allow Polkadot native assets to be represented via a standard [ERC-20 interface](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/assets-erc20/ERC20.sol){target=\_blank} through a precompiled contract. When these assets are registered on Moonbeam, they can be set as XCM execution fee assets. Consequently, when a user transfers such an asset to Moonbeam, a small part of the amount will be used to cover the XCM execution fees.
In addition, ERC-20s that are deployed to Moonbeam can be sent to other chains in the Polkadot ecosystem via XCM. Consequently, from a developer's perspective, XC-20s are ERC-20 tokens with the added benefit of being an XCM cross-chain asset, and dApps can easily support them through a familiar ERC-20 interface.

To send XC-20s across the Polkadot ecosystem from Moonbeam, developers need to use the [Polkadot XCM Pallet](/builders/interoperability/xcm/xc20/send-xc20s/xcm-pallet/){target=\_blank} for transfers via the Substrate API and the [X-Tokens Precompile](/builders/interoperability/xcm/xc20/send-xc20s/xtokens-precompile/){target=\_blank} or the [XCM Precompile](/builders/interoperability/xcm/xc20/send-xc20s/eth-api/){target=\_blank} for transfers via the Ethereum API.
Another unique feature of Moonbeam is the ability to initiate XCM actions from EVM smart contracts or to call its EVM through XCM messages via remote execution. This unlocks a new set of possibilities, where contracts on Moonbeam can access parachain-specific functionalities via XCM, or other parachain ecosystems can use EVM smart contracts on Moonbeam to expand their functions.
The following sections provide a high-level overview of the main use cases mentioned before.
### XCM Transfers between Moonbeam & Polkadot {: #transfers-moonbeam-polkadot }
As Moonbeam is a parachain within the Polkadot ecosystem, a straightforward implementation of XCM + VMP is DOT transfers from/to Polkadot/Moonbeam. To this end, DOT was registered as [_xcDOT_](https://moonscan.io/token/0xffffffff1fcacbd218edc0eba20fc2308c778080){target=\_blank} on Moonbeam.
Alice (Polkadot) wants to transfer a certain amount of DOT from Polkadot to her account on Moonbeam, named Alith. Therefore, she initiates an XCM that expresses her intentions. For such transfers, Moonbeam owns a Sovereign account on Polkadot.
Consequently, the XCM message execution on Polkadot will transfer the amount of DOT to Moonbeam's Sovereign account on Polkadot. Once the assets are deposited, the second part of the message is sent to Moonbeam.
Moonbeam will locally execute the action the XCM message is programmed to do. In this case, it is to mint and transfer the same amount of _xcDOT_ to the account defined by Alice, which in this case is Alith. The fee to execute the XCM in the target parachain is paid in the asset being transferred (_xcDOT_ for this example).

Note the following:
- The Alice and Alith accounts can be different. For example, Polkadot's accounts are SR25519 (or ED25519), while Moonbeam's are ECDSA (Ethereum-styled) accounts. They can also have different owners
- There is a certain degree of trust where one chain relies on the other to execute its part of the XCM message. This is programmed at a runtime level so that it can be easily verified
- For this example, _xcDOT_ is a wrapped representation of the original DOT being held in Moonbeam's Sovereign account on Polkadot. _xcDOT_ can be transferred within Moonbeam at any time, and they can be redeemed for DOT on a 1:1 basis as well (minus some fees)
Alith deposited her _xcDOT_ in a liquidity pool. Next, Charleth acquires some _xcDOT_ by swapping against that liquidity pool, and he wants to transfer some _xcDOT_ to Charley's Polkadot account. Therefore, he initiates an XCM that expresses his intentions.
Consequently, the XCM message execution on Moonbeam will burn the number of _xcDOT_. Once the assets are burned, the second part of the message is sent to Polkadot.
Polkadot will execute the action the XCM message is programmed to do locally. In this case, it is to transfer the same amount of _xcDOT_ burned from the Moonbeam Sovereign account to the account defined by Charleth, which in this case is Charley.

### XCM Transfers between Moonbeam & Other Parachains {: #transfers-moonbeam-other-parachains }
Since Moonbeam is a parachain within the Polkadot ecosystem, a straightforward implementation of XCM and XCMP asset transfers from and to Moonbeam and other parachains. This section gives a high-level overview of the main differences compared to XCMs from Polkadot/Moonbeam.
The first requirement is that a bidirectional channel between the parachains must exist, and the asset being transferred must be registered in the target parachain. Only when both conditions are met can XCMs be sent between parachains.
Then, when Alith (Moonbeam) transfers a certain amount of GLMR from Moonbeam to another account (Alice) in a target parachain, tokens are sent to a Sovereign Account owned by that target parachain on Moonbeam.
As the XCM message is executed in the target parachain, it is expected that this will mint and transfer the same amount of _xcGLMR_ (cross-chain GLMR) to the account defined by Alith, which in this case is Alice. The fee to execute the XCM in the target parachain is paid in the transferred asset (_xcGLMR_ for this example).

As explained in the previous section, the process is similar for _xcGLMR_ to move back to Moonbeam. First, the XCM message execution burns the number of _xcGLMR_ returned to Moonbeam. Once burned, the remnant part of the message is sent to Moonbeam via the relay chain. Moonbeam will locally execute the XCM message's and transfer GLMR (the same amount of burned _xcGLMR_) from the target parachain Sovereign account to the specified address.
### Remote Execution between Other Chains & Moonbeam {: #execution-chains-moonbeam }
As mentioned before, XCM also enables remote execution from/to Moonbeam to other chains in the Polkadot ecosystem.
Similarly to the other use cases, it is necessary for XCM-specific channels to be established before remote execution can happen between the chains. Channels are general-purpose, so they can be used for both asset transfers and remote execution.
Another important component is the asset for which the remote execution fees are paid. On Moonbeam, when an XC-20 is registered, it can be set as an XCM execution fee asset. Consequently, when transferring that XC-20 to Moonbeam, the XCM execution fee is deducted from the amount being transferred. For remote execution, users can include a small amount of tokens in the XCM message to cover XCM execution fees.
Alice (Polkadot) wants to perform a certain remote action through a smart contract on Moonbeam. Therefore, she initiates an XCM that expresses her intentions; she must have previously funded the XCM execution account she owns on Moonbeam with either GLMR or _xcDOT_.
Moonbeam will locally execute the action the XCM message is programmed to do. In this case, it is to withdraw the asset decided by Alice for the XCM execution fee and buy some execution time on Moonbeam to execute the smart contract call on Moonbeam's EVM.
You can read more about the flow in detail on the [Remote Execution](/builders/interoperability/xcm/remote-execution/overview/){target=\_blank} page.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/interoperability/xcm/remote-execution/overview/
--- BEGIN CONTENT ---
---
title: Remote Execution Overview
description: Learn the basics of remote execution via XCM messages, which allow users to execute actions on other blockchains using accounts they control remotely via XCM.
categories: XCM Remote Execution, Basics
---
# Remote Execution via XCM
## Introduction {: #introduction }
The [Cross-Consensus Message (XCM)](https://wiki.polkadot.com/learn/learn-xcm/){target=\_blank} format defines how messages can be sent between interoperable blockchains. This format opens the door to sending an XCM message that executes an arbitrary set of bytes in a Moonbeam-based network, the relay chain, or other parachains in the Polkadot/Kusama ecosystems.
Remote execution via XCM opens a new set of possibilities for cross-chain interactions, from chains executing actions on other chains to users performing remote actions without switching chains.
This page covers the fundamentals of XCM remote execution. If you want to learn how to perform remote execution via XCM, please refer to the [Remote Execution via the Substrate API](/builders/interoperability/xcm/remote-execution/substrate-calls/xcm-transactor-pallet/){target=\_blank} or the [Remote Execution via the Ethereum API](/builders/interoperability/xcm/xc20/send-xc20s/xtokens-precompile/){target=\_blank} guides.
## Execution Origin {: #execution-origin }
Generally speaking, all transactions have an origin, which is where a call comes from. Ethereum transactions have only one origin type, the `msg.sender`, which is the account that initiated the transaction.
Substrate-based transactions are more complex, as they can have different origins with different privilege levels. This is similar to having an EVM smart contract call with a specific `require` statement in which the call must come from an allowed address. In contrast, these privilege levels are programmed in the Substrate-based runtime itself.
Origins are super important across different components of the Substrate runtime and, hence, the Moonbeam runtime. For example, they define the authority level they inherit in the [on-chain governance implementation](/learn/features/governance/){target=\_blank}.
During the execution of an XCM message, the origin defines the context in which the XCM is being executed. By default, the XCM is executed by the source chain's Sovereign account in the destination chain. This Polkadot-specific property of having remote origins that are calculated when executing XCM is known as [Computed Origins](/builders/interoperability/xcm/remote-execution/computed-origins/){target=\_blank} (formerly known as Multilocation Derivative Accounts).
Depending on the destination chain's configuration, including the `DescendOrigin` XCM instruction can mutate the origin from which the XCM message is executed. This property is significant for remote XCM execution, as the action being executed considers the context of the newly mutated origin and not the source chain's Sovereign account.
## XCM Instructions for Remote Execution {: #xcm-instructions-remote-execution }
The core XCM instructions required to perform remote execution on Moonbeam (as an example) via XCM are the following:
- [`DescendOrigin`](/builders/interoperability/xcm/core-concepts/instructions/#descend-origin){target=\_blank} - (optional) gets executed in Moonbeam. Mutates the origin to create a new Computed Origin that represents a keyless account controlled via XCM by the sender in the source chain
- [`WithdrawAsset`](/builders/interoperability/xcm/core-concepts/instructions/#withdraw-asset){target=\_blank} - gets executed in Moonbeam. Takes funds from the Computed Origin
- [`BuyExecution`](/builders/interoperability/xcm/core-concepts/instructions/#buy-execution){target=\_blank} - gets executed in Moonbeam. Uses the funds taken by the previous XCM instruction to pay for the XCM execution, including the remote call
- [`Transact`](/builders/interoperability/xcm/core-concepts/instructions/#transact){target=\_blank} - gets executed in Moonbeam. Executes the arbitrary bytes provided in the XCM instruction
The XCM instructions detailed above can be complemented by other XCM instructions to handle certain scenarios, like failure on execution, more accurately. One example is the inclusion of [`SetAppendix`](/builders/interoperability/xcm/core-concepts/instructions/#set-appendix){target=\_blank}, [`RefundSurplus`](/builders/interoperability/xcm/core-concepts/instructions/#refund-surplus){target=\_blank}, and [`Deposit`](/builders/interoperability/xcm/core-concepts/instructions/#deposit-asset){target=\_blank}.
## General Remote Execution via XCM Flow {: #general-remote-execution-via-xcm-flow }
A user initiates a transaction in the source chain through a pallet that builds the XCM with at least the [required XCM instructions for remote execution](#xcm-instructions-remote-execution). The transaction is executed in the source chain, which sends an XCM message with the given instructions to the destination chain.
The XCM message arrives at the destination chain, which executes it. It is executed with the source chain's Sovereign account as a Computed Origin by default. One example that uses this type of origin is when chains open or accept an HRMP channel on the relay chain.
If the XCM message included a [`DescendOrigin`](/builders/interoperability/xcm/core-concepts/instructions/#descend-origin){target=\_blank} instruction, the destination chain may mutate the origin to calculate a new Computed Origin (as is the case with Moonbeam-based networks).
Next, [`WithdrawAsset`](/builders/interoperability/xcm/core-concepts/instructions/#withdraw-asset){target=\_blank} takes funds from the Computed Origin (either a Sovereign account or mutated), which are then used to pay for the XCM execution through the [`BuyExecution`](/builders/interoperability/xcm/core-concepts/instructions/#buy-execution){target=\_blank} XCM instruction. Note that on both instructions, you need to specify which asset you want to use. In addition, you must include the bytes to be executed in the amount of execution to buy.
Lastly, [`Transact`](/builders/interoperability/xcm/core-concepts/instructions/#transact){target=\_blank} executes an arbitrary set of bytes that correspond to a pallet and function in the destination chain. You have to specify the type of origin to use (typically `SovereignAccount`) and the weight required to execute the bytes (similar to gas in the Ethereum realm).

--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/interoperability/xcm/xc20/overview/
--- BEGIN CONTENT ---
---
title: XC-20s and Cross-Chain Assets
description: Learn about the types of cross-chain assets on Moonbeam, in particular, local and external XC-20s, and view a list of the external XC-20s on Moonbeam.
categories: Basics, XC-20
---
# Overview of XC-20s
## Introduction {: #introduction }
The [Cross-Consensus Message (XCM)](https://wiki.polkadot.com/learn/learn-xcm/){target=\_blank} format provides a universal way for blockchains to exchange messages and transfer assets. To extend this interoperability to the EVM, Moonbeam introduced XC-20s, ERC-20 tokens on Moonbeam that are fully compatible with XCM transfers.
Any ERC-20 deployed on Moonbeam can be configured as an XC-20, making it accessible to any chain connected via XCM. This allows EVM-focused developers to work with familiar ERC-20 workflows while benefiting from Polkadot’s native cross-chain functionality, all without needing Substrate-specific expertise.
From a technical standpoint, local XC-20s are ERC-20 tokens originating on Moonbeam (including bridged tokens deemed native once issued on Moonbeam), whereas external XC-20s are wrapped representations of tokens whose canonical ledger exists on another parachain or the relay chain. In all cases, XC-20s function just like standard ERC-20s—supporting common EVM-based use cases (such as DeFi, DEXs, and lending platforms)—but with the added advantage of seamless cross-chain operability.

This page aims to cover the basics on XC-20s; if you want to learn how to interact with or transfer XC-20s, please refer to the [Send XC-20s guide](/builders/interoperability/xcm/xc20/send-xc20s/overview/){target=\_blank}.
## Types of XC-20s {: #types-of-xc-20s }
There are two types of XC-20s: local and external.
### What are Local XC-20s? {: #local-xc20s }
Local XC-20s are all ERC-20s that exist on the EVM, and that can be transferred cross-chain through XCM. For local XC-20s to be transferred to another parachain, the asset must be registered on that chain. When transferring local XC-20s, the underlying tokens reside in the destination chain's Sovereign account on Moonbeam. A [sovereign account](/builders/interoperability/xcm/core-concepts/sovereign-accounts/){target=\_blank} is a keyless account governed by a blockchain runtime—rather than an individual—that can hold assets and interact with other chains. Local XC-20s must follow [the ERC-20 interface outlined in this guide](/builders/interoperability/xcm/xc20/interact/#the-erc20-interface){target=\_blank}. They must implement the standard ERC-20 function signatures, including the correct function selector of the `transfer` function as described in [EIP-20](https://eips.ethereum.org/EIPS/eip-20){target=\_blank}. However, additional functionality can still be added as long as it doesn’t break the base methods.
Creating a local XC-20 is equivalent to deploying a standard ERC-20 and enabling cross-chain features on any Moonbeam network.
### What are External XC-20s? {: #external-xc20s }
External XC-20s are cross-chain tokens originating from another parachain or the relay chain, and they are represented on Moonbeam as ERC-20 tokens. The original tokens remain locked in a Moonbeam sovereign account on their home chain, while the wrapped ERC-20 representation can be freely utilized on Moonbeam. When you transfer external XC-20s, the canonical assets remain in the sovereign account on their source chain, while the ERC-20 representation is what circulates on Moonbeam.
External XC-20s all have _xc_ prepended to their names to distinguish them as cross-chain assets. For example, DOT, native to the Polkadot relay chain, is known as xcDOT when represented as an XC-20 on Moonbeam.
### Local XC-20s vs External XC-20s {: #local-xc-20s-vs-external-xc-20s }
Local XC-20s are EVM-native ERC-20 tokens whose “home” (or reserve chain) is Moonbeam from a Polkadot perspective. This includes tokens originally bridged in from outside Polkadot (for example, Wormhole-wrapped ETH), because once they’re issued on Moonbeam as ERC-20s, Polkadot views them as local to Moonbeam. When local XC-20s are transferred to another parachain, the tokens move into that chain’s sovereign account on Moonbeam.
External XC-20s, on the other hand, are ERC-20 representations of tokens whose canonical ledger remains on another parachain or the relay chain. Moonbeam holds the “wrapped” version, while the underlying tokens stay locked in Moonbeam’s sovereign account on the originating chain.
From a cross-chain transfer perspective, local and external XC-20s can be sent through Polkadot’s XCM infrastructure using the Ethereum or Substrate API. Because the underlying asset is an ERC-20 with EVM bytecode following the [EIP-20 token standard](https://eips.ethereum.org/EIPS/eip-20){target=\_blank}, both transfers initiated via the Substrate and Ehereum APIs generate EVM logs visible to EVM-based explorers such as [Moonscan](https://moonscan.io){target=\_blank}. In contrast, you can't send a regular ERC-20 transfer using the Substrate API. Aside from cross-chain transfers through XCM, all other XC-20 interactions (such as querying balances or adjusting allowances) must occur in the EVM.
Cross-chain transfers of XC-20s are executed via the Polkadot XCM Pallet, which utilizes regular mint, burn, and transfer mechanisms of ERC-20s for the XCM asset flow. If you’d like to learn how to send XC-20s using that pallet, refer to the [Using the Polkadot XCM Pallet](/builders/interoperability/xcm/xc20/send-xc20s/xcm-pallet/){target=\_blank} guide.
## Asset Reserves {: #asset-reserves }
When transferring tokens across chains in the Polkadot or Kusama ecosystems, each token has a “reserve” chain that holds its canonical ledger—the source of truth for minting, burning, and supply management. For XC-20s, understanding which chain is the reserve determines whether the asset is managed locally on Moonbeam or remotely on another chain.
Regardless of where the reserve is located, XC-20s on Moonbeam are still ERC-20 tokens that developers and users can interact with in the EVM. However, from an XCM perspective, the reserve chain determines how the tokens are locked, unlocked, minted, or burned behind the scenes when performing cross-chain operations.
### Local Reserve Assets {: #local-reserve-assets }
A local reserve asset on Moonbeam is a token whose canonical ledger—from an XCM perspective—resides natively on Moonbeam. In other words, Moonbeam is the asset’s home chain, where minting and burning take place.
For example, Wormhole-wrapped ETH (wETH) is considered a local reserve asset on Moonbeam, even though Ethereum is the ultimate source of ETH. Once ETH is wrapped by Wormhole and enters the Polkadot ecosystem via Moonbeam, wETH can be transferred to other parachains through [Moonbeam Routed Liquidity (MRL)](/builders/interoperability/mrl/){target=\_blank}.
The important caveat is that, on a purely Ethereum-level view, ETH remains governed by and minted on Ethereum. However, from an XCM standpoint, wETH on Moonbeam is treated as a local reserve asset, meaning the canonical supply of wETH (as far as Polkadot ecosystems are concerned) exists on Moonbeam.
### Remote Reserve Assets {: #remote-reserve-assets }
A remote reserve asset is a token whose canonical ledger—the source of truth for minting and burning—resides on a chain different from where it’s currently in use. In the case of xcDOT on Moonbeam, the underlying DOT tokens representing the xcDOT remain locked in Moonbeam’s sovereign account on the Polkadot relay chain, while xcDOT functions as a wrapped representation in Moonbeam’s EVM environment.
Users can hold and transact with xcDOT on Moonbeam (for DeFi, governance, and more), knowing that the underlying DOT is safely locked on the relay chain. At any point, the wrapped xcDOT can be redeemed for the original DOT, effectively burning the xcDOT and unlocking the corresponding DOT tokens on Polkadot.
## Current List of External XC-20s {: #current-xc20-assets }
The current list of available external XC-20 assets per network is as follows:
=== "Moonbeam"
| Origin | Symbol | XC-20 Address |
|:---------------------:|:---------:|:------------------------------------------------------------------------------------------------------------------------------------:|
| Polkadot | xcDOT | [0xFfFFfFff1FcaCBd218EDc0EbA20Fc2308C778080](https://moonscan.io/token/0xFfFFfFff1FcaCBd218EDc0EbA20Fc2308C778080){target=\_blank} |
| Acala | xcaUSD | [0xfFfFFFFF52C56A9257bB97f4B2b6F7B2D624ecda](https://moonscan.io/token/0xfFfFFFFF52C56A9257bB97f4B2b6F7B2D624ecda){target=\_blank} |
| Acala | xcACA | [0xffffFFffa922Fef94566104a6e5A35a4fCDDAA9f](https://moonscan.io/token/0xffffFFffa922Fef94566104a6e5A35a4fCDDAA9f){target=\_blank} |
| Acala | xcLDOT | [0xFFfFfFffA9cfFfa9834235Fe53f4733F1b8B28d4](https://moonscan.io/token/0xFFfFfFffA9cfFfa9834235Fe53f4733F1b8B28d4){target=\_blank} |
| Apillon | xcNCTR | [0xFfFFfFfF8A9736B44EbF188972725bED67BF694E](https://moonscan.io/token/0xFfFFfFfF8A9736B44EbF188972725bED67BF694E){target=\_blank} |
| Astar | xcASTR | [0xFfFFFfffA893AD19e540E172C10d78D4d479B5Cf](https://moonscan.io/token/0xFfFFFfffA893AD19e540E172C10d78D4d479B5Cf){target=\_blank} |
| Bifrost | xcBNC | [0xFFffffFf7cC06abdF7201b350A1265c62C8601d2](https://moonscan.io/token/0xFFffffFf7cC06abdF7201b350A1265c62C8601d2){target=\_blank} |
| Bifrost | xcBNCS | [0xfFfffffF6aF229AE7f0F4e0188157e189a487D59](https://moonscan.io/token/0xfFfffffF6aF229AE7f0F4e0188157e189a487D59){target=\_blank} |
| Bifrost | xcFIL | [0xfFFfFFFF6C57e17D210DF507c82807149fFd70B2](https://moonscan.io/token/0xfFFfFFFF6C57e17D210DF507c82807149fFd70B2){target=\_blank} |
| Bifrost | xcvASTR | [0xFffFffff55C732C47639231a4C4373245763d26E](https://moonscan.io/token/0xFffFffff55C732C47639231a4C4373245763d26E){target=\_blank} |
| Bifrost | xcvBNC | [0xffFffFff31d724194b6A76e1d639C8787E16796b](https://moonscan.io/token/0xffFffFff31d724194b6A76e1d639C8787E16796b){target=\_blank} |
| Bifrost | xcvDOT | [0xFFFfffFf15e1b7E3dF971DD813Bc394deB899aBf](https://moonscan.io/token/0xFFFfffFf15e1b7E3dF971DD813Bc394deB899aBf){target=\_blank} |
| Bifrost | xcvFIL | [0xFffffFffCd0aD0EA6576B7b285295c85E94cf4c1](https://moonscan.io/token/0xFffffFffCd0aD0EA6576B7b285295c85E94cf4c1){target=\_blank} |
| Bifrost | xcvGLMR | [0xFfFfFFff99dABE1a8De0EA22bAa6FD48fdE96F6c](https://moonscan.io/token/0xFfFfFFff99dABE1a8De0EA22bAa6FD48fdE96F6c){target=\_blank} |
| Bifrost | xcvMANTA | [0xFFfFFfFfdA2a05FB50e7ae99275F4341AEd43379](https://moonscan.io/token/0xFFfFFfFfdA2a05FB50e7ae99275F4341AEd43379){target=\_blank} |
| Centrifuge | xcCFG | [0xFFfFfFff44bD9D2FFEE20B25D1Cf9E78Edb6Eae3](https://moonscan.io/token/0xFFfFfFff44bD9D2FFEE20B25D1Cf9E78Edb6Eae3){target=\_blank} |
| Composable | xcIBCMOVR | [0xFfFfffFF3AFcd2cAd6174387df17180a0362E592](https://moonscan.io/token/0xFfFfffFF3AFcd2cAd6174387df17180a0362E592){target=\_blank} |
| Composable | xcIBCPICA | [0xfFFFFfFFABe9934e61db3b11be4251E6e869cf59](https://moonscan.io/token/0xfFFFFfFFABe9934e61db3b11be4251E6e869cf59){target=\_blank} |
| Composable | xcIBCIST | [0xfFfFffff6A3977d5B65D1044FD744B14D9Cef932](https://moonscan.io/token/0xfFfFffff6A3977d5B65D1044FD744B14D9Cef932){target=\_blank} |
| Composable | xcIBCBLD | [0xFffFffff9664be0234ea4dc64558F695C4f2A9EE](https://moonscan.io/token/0xFffFffff9664be0234ea4dc64558F695C4f2A9EE){target=\_blank} |
| Composable | xcIBCTIA | [0xFFFfFfff644a12F6F01b754987D175F5A780A75B](https://moonscan.io/token/0xFFFfFfff644a12F6F01b754987D175F5A780A75B){target=\_blank} |
| Composable | xcIBCATOM | [0xffFFFffF6807D5082ff2f6F86BdE409245e2D953](https://moonscan.io/token/0xffFFFffF6807D5082ff2f6F86BdE409245e2D953){target=\_blank} |
| Darwinia | xcRING | [0xFfffFfff5e90e365eDcA87fB4c8306Df1E91464f](https://moonscan.io/token/0xFfffFfff5e90e365eDcA87fB4c8306Df1E91464f){target=\_blank} |
| DED | xcDED | [0xfFffFFFf5da2d7214D268375cf8fb1715705FdC6](https://moonscan.io/token/0xfFffFFFf5da2d7214D268375cf8fb1715705FdC6){target=\_blank} |
| Equilibrium | xcEQ | [0xFffFFfFf8f6267e040D8a0638C576dfBa4F0F6D6](https://moonscan.io/token/0xFffFFfFf8f6267e040D8a0638C576dfBa4F0F6D6){target=\_blank} |
| Equilibrium | xcEQD | [0xFFffFfFF8cdA1707bAF23834d211B08726B1E499](https://moonscan.io/token/0xFFffFfFF8cdA1707bAF23834d211B08726B1E499){target=\_blank} |
| HydraDX | xcHDX | [0xFFFfFfff345Dc44DDAE98Df024Eb494321E73FcC](https://moonscan.io/token/0xFFFfFfff345Dc44DDAE98Df024Eb494321E73FcC){target=\_blank} |
| Interlay | xcIBTC | [0xFFFFFfFf5AC1f9A51A93F5C527385edF7Fe98A52](https://moonscan.io/token/0xFFFFFfFf5AC1f9A51A93F5C527385edF7Fe98A52){target=\_blank} |
| Interlay | xcINTR | [0xFffFFFFF4C1cbCd97597339702436d4F18a375Ab](https://moonscan.io/token/0xFffFFFFF4C1cbCd97597339702436d4F18a375Ab){target=\_blank} |
| Manta | xcMANTA | [0xfFFffFFf7D3875460d4509eb8d0362c611B4E841](https://moonscan.io/token/0xfFFffFFf7D3875460d4509eb8d0362c611B4E841){target=\_blank} |
| Nodle | xcNODL | [0xfffffffFe896ba7Cb118b9Fa571c6dC0a99dEfF1](https://moonscan.io/token/0xfffffffFe896ba7Cb118b9Fa571c6dC0a99dEfF1){target=\_blank} |
| OriginTrail Parachain | xcNEURO | [0xFfffffFfB3229c8E7657eABEA704d5e75246e544](https://moonscan.io/token/0xFfffffFfB3229c8E7657eABEA704d5e75246e544){target=\_blank} |
| Parallel | xcPARA | [0xFfFffFFF18898CB5Fe1E88E668152B4f4052A947](https://moonscan.io/token/0xFfFffFFF18898CB5Fe1E88E668152B4f4052A947){target=\_blank} |
| Peaq | xcPEAQ | [0xFffFFFFFEC4908b74688a01374f789B48E9a3eab](https://moonscan.io/token/0xFffFFFFFEC4908b74688a01374f789B48E9a3eab){target=\_blank} |
| Pendulum | xcPEN | [0xffFFfFFf2257622F345E1ACDe0D4f46D7d1D77D0](https://moonscan.io/token/0xffFFfFFf2257622F345E1ACDe0D4f46D7d1D77D0){target=\_blank} |
| Phala | xcPHA | [0xFFFfFfFf63d24eCc8eB8a7b5D0803e900F7b6cED](https://moonscan.io/token/0xFFFfFfFf63d24eCc8eB8a7b5D0803e900F7b6cED){target=\_blank} |
| Polkadex | xcPDEX | [0xfFffFFFF43e0d9b84010b1b67bA501bc81e33C7A](https://moonscan.io/token/0xfFffFFFF43e0d9b84010b1b67bA501bc81e33C7A){target=\_blank} |
| Polkadot Asset Hub | xcPINK | [0xfFfFFfFf30478fAFBE935e466da114E14fB3563d](https://moonscan.io/token/0xfFfFFfFf30478fAFBE935e466da114E14fB3563d){target=\_blank} |
| Polkadot Asset Hub | xcSTINK | [0xFffFffFf54c556bD1d0F64ec6c78f1B477525E56](https://moonscan.io/token/0xFffFffFf54c556bD1d0F64ec6c78f1B477525E56){target=\_blank} |
| Polkadot Asset Hub | xcUSDC | [0xFFfffffF7D2B0B761Af01Ca8e25242976ac0aD7D](https://moonscan.io/token/0xFFfffffF7D2B0B761Af01Ca8e25242976ac0aD7D){target=\_blank} |
| Polkadot Asset Hub | xcUSDT | [0xFFFFFFfFea09FB06d082fd1275CD48b191cbCD1d](https://moonscan.io/token/0xFFFFFFfFea09FB06d082fd1275CD48b191cbCD1d){target=\_blank} |
| Polkadot Asset Hub | xcWIFD | [0xfffffffF2e1D1ac9eA1686255bEfe995B31abc96](https://moonscan.io/token/0xfffffffF2e1D1ac9eA1686255bEfe995B31abc96){target=\_blank} |
| Snowbridge | WBTC.e | [0xfFffFFFf1B4Bb1ac5749F73D866FfC91a3432c47](https://moonscan.io/address/0xffffffff1B4BB1AC5749F73D866FFC91A3432C47){target=\_blank} |
| Snowbridge | wstETH.e | [0xFfFFFfFF5D5DEB44BF7278DEE5381BEB24CB6573](https://moonscan.io/token/0xFfFFFfFF5D5DEB44BF7278DEE5381BEB24CB6573){target=\_blank} |
| Snowbridge | WETH.e | [0xfFffFFFF86829AFE1521AD2296719DF3ACE8DED7](https://moonscan.io/token/0xfFffFFFF86829AFE1521AD2296719DF3ACE8DED7){target=\_blank} |
| Subsocial | xcSUB | [0xfFfFffFf43B4560Bc0C451a3386E082bff50aC90](https://moonscan.io/token/0xfFfFffFf43B4560Bc0C451a3386E082bff50aC90){target=\_blank} |
| Unique | xcUNQ | [0xFffffFFFD58f77E6693CFB99EbE273d73C678DC2](https://moonscan.io/token/0xFffffFFFD58f77E6693CFB99EbE273d73C678DC2){target=\_blank} |
| Zeitgeist | xcZTG | [0xFFFFfffF71815ab6142E0E20c7259126C6B40612](https://moonscan.io/token/0xFFFFfffF71815ab6142E0E20c7259126C6B40612){target=\_blank} |
_*You can check each [Asset ID](https://polkadot.js.org/apps/?rpc=wss://wss.api.moonbeam.network#/assets){target=\_blank} on Polkadot.js Apps_
=== "Moonriver"
| Origin | Symbol | XC-20 Address |
|:----------------:|:-------:|:--------------------------------------------------------------------------------------------------------------------------------------------:|
| Kusama | xcKSM | [0xFfFFfFff1FcaCBd218EDc0EbA20Fc2308C778080](https://moonriver.moonscan.io/token/0xffffffff1fcacbd218edc0eba20fc2308c778080){target=\_blank} |
| Bifrost | xcBNC | [0xFFfFFfFFF075423be54811EcB478e911F22dDe7D](https://moonriver.moonscan.io/token/0xFFfFFfFFF075423be54811EcB478e911F22dDe7D){target=\_blank} |
| Bifrost | xcvBNC | [0xFFffffff3646A00f78caDf8883c5A2791BfCDdc4](https://moonriver.moonscan.io/token/0xFFffffff3646A00f78caDf8883c5A2791BfCDdc4){target=\_blank} |
| Bifrost | xcvKSM | [0xFFffffFFC6DEec7Fc8B11A2C8ddE9a59F8c62EFe](https://moonriver.moonscan.io/token/0xFFffffFFC6DEec7Fc8B11A2C8ddE9a59F8c62EFe){target=\_blank} |
| Bifrost | xcvMOVR | [0xfFfffFfF98e37bF6a393504b5aDC5B53B4D0ba11](https://moonriver.moonscan.io/token/0xfFfffFfF98e37bF6a393504b5aDC5B53B4D0ba11){target=\_blank} |
| Calamari | xcKMA | [0xffffffffA083189F870640B141AE1E882C2B5BAD](https://moonriver.moonscan.io/token/0xffffffffA083189F870640B141AE1E882C2B5BAD){target=\_blank} |
| Crab | xcCRAB | [0xFFFffFfF8283448b3cB519Ca4732F2ddDC6A6165](https://moonriver.moonscan.io/token/0xFFFffFfF8283448b3cB519Ca4732F2ddDC6A6165){target=\_blank} |
| Crust-Shadow | xcCSM | [0xffFfFFFf519811215E05eFA24830Eebe9c43aCD7](https://moonriver.moonscan.io/token/0xffFfFFFf519811215E05eFA24830Eebe9c43aCD7){target=\_blank} |
| Heiko | xcHKO | [0xffffffFF394054BCDa1902B6A6436840435655a3](https://moonriver.moonscan.io/token/0xffffffFF394054BCDa1902B6A6436840435655a3){target=\_blank} |
| Integritee | xcTEER | [0xFfFfffFf4F0CD46769550E5938F6beE2F5d4ef1e](https://moonriver.moonscan.io/token/0xFfFfffFf4F0CD46769550E5938F6beE2F5d4ef1e){target=\_blank} |
| Karura | xcKAR | [0xFfFFFFfF08220AD2E6e157f26eD8bD22A336A0A5](https://moonriver.moonscan.io/token/0xFfFFFFfF08220AD2E6e157f26eD8bD22A336A0A5){target=\_blank} |
| Karura | xcaSEED | [0xFfFffFFfa1B026a00FbAA67c86D5d1d5BF8D8228](https://moonriver.moonscan.io/token/0xFfFffFFfa1B026a00FbAA67c86D5d1d5BF8D8228){target=\_blank} |
| Khala | xcPHA | [0xffFfFFff8E6b63d9e447B6d4C45BDA8AF9dc9603](https://moonriver.moonscan.io/token/0xffFfFFff8E6b63d9e447B6d4C45BDA8AF9dc9603){target=\_blank} |
| Kintsugi | xcKINT | [0xfffFFFFF83F4f317d3cbF6EC6250AeC3697b3fF2](https://moonriver.moonscan.io/token/0xfffFFFFF83F4f317d3cbF6EC6250AeC3697b3fF2){target=\_blank} |
| Kintsugi | xckBTC | [0xFFFfFfFfF6E528AD57184579beeE00c5d5e646F0](https://moonriver.moonscan.io/token/0xFFFfFfFfF6E528AD57184579beeE00c5d5e646F0){target=\_blank} |
| Kusama Asset Hub | xcRMRK | [0xffffffFF893264794d9d57E1E0E21E0042aF5A0A](https://moonriver.moonscan.io/token/0xffffffFF893264794d9d57E1E0E21E0042aF5A0A){target=\_blank} |
| Kusama Asset Hub | xcUSDT | [0xFFFFFFfFea09FB06d082fd1275CD48b191cbCD1d](https://moonriver.moonscan.io/token/0xFFFFFFfFea09FB06d082fd1275CD48b191cbCD1d){target=\_blank} |
| Litmus | xcLIT | [0xfffFFfFF31103d490325BB0a8E40eF62e2F614C0](https://moonriver.moonscan.io/token/0xfffFFfFF31103d490325BB0a8E40eF62e2F614C0){target=\_blank} |
| Mangata | xcMGX | [0xffFfFffF58d867EEa1Ce5126A4769542116324e9](https://moonriver.moonscan.io/token/0xffFfFffF58d867EEa1Ce5126A4769542116324e9){target=\_blank} |
| Picasso | xcPICA | [0xFffFfFFf7dD9B9C60ac83e49D7E3E1f7A1370aD2](https://moonriver.moonscan.io/token/0xFffFfFFf7dD9B9C60ac83e49D7E3E1f7A1370aD2){target=\_blank} |
| Robonomics | xcXRT | [0xFffFFffF51470Dca3dbe535bD2880a9CcDBc6Bd9](https://moonriver.moonscan.io/token/0xFffFFffF51470Dca3dbe535bD2880a9CcDBc6Bd9){target=\_blank} |
| Shiden | xcSDN | [0xFFFfffFF0Ca324C842330521525E7De111F38972](https://moonriver.moonscan.io/token/0xFFFfffFF0Ca324C842330521525E7De111F38972){target=\_blank} |
| Tinkernet | xcTNKR | [0xfFFfFffF683474B842852111cc31d470bD8f5081](https://moonriver.moonscan.io/token/0xffffffff683474b842852111cc31d470bd8f5081){target=\_blank} |
| Turing | xcTUR | [0xfFffffFf6448d0746f2a66342B67ef9CAf89478E](https://moonriver.moonscan.io/token/0xfFffffFf6448d0746f2a66342B67ef9CAf89478E){target=\_blank} |
_*You can check each [Asset ID](https://polkadot.js.org/apps/?rpc=wss://wss.api.moonriver.moonbeam.network#/assets){target=\_blank} on Polkadot.js Apps_
=== "Moonbase Alpha"
| Origin | Symbol | XC-20 Address |
|:--------------------:|:------:|:-------------------------------------------------------------------------------------------------------------------------------------------:|
| Relay Chain Alphanet | xcUNIT | [0xFfFFfFff1FcaCBd218EDc0EbA20Fc2308C778080](https://moonbase.moonscan.io/token/0xFfFFfFff1FcaCBd218EDc0EbA20Fc2308C778080){target=\_blank} |
_*You can check each [Asset ID](https://polkadot.js.org/apps/?rpc=wss://wss.api.moonbase.moonbeam.network#/assets){target=\_blank} on Polkadot.js Apps_
### Retrieve List of External XC-20s and Their Metadata {: #list-xchain-assets }
To fetch a list of the currently available external XC-20s along with their associated metadata, you can query the chain state using the [Polkadot.js API](/builders/substrate/libraries/polkadot-js-api/){target=\_blank}. You'll take the following steps:
1. Create an API provider for the network you'd like to get the list of assets for. You can use the following WSS endpoints for each network:
=== "Moonbeam"
```text
wss://wss.api.moonbeam.network
```
=== "Moonriver"
```text
wss://wss.api.moonriver.moonbeam.network
```
=== "Moonbase Alpha"
```text
{{ networks.moonbase.wss_url }}
```
2. Query the `assets` pallet for all assets
3. Iterate over the list of assets to get all of the asset IDs along with their associated metadata
```js
import { ApiPromise, WsProvider } from '@polkadot/api';
const getXc20s = async () => {
try {
const substrateProvider = new WsProvider('INSERT_WSS_ENDPOINT');
const api = await ApiPromise.create({ provider: substrateProvider });
const assets = await api.query.assets.asset.entries();
await Promise.all(
assets.map(async ([{ args: [id] }]) => {
try {
const metadata = await api.query.assets.metadata(id);
const humanMetadata = metadata.toHuman();
console.log(`\nAsset ID: ${id}`);
console.log('Metadata:');
console.log(' Name:', humanMetadata.name);
console.log(' Symbol:', humanMetadata.symbol);
console.log(' Decimals:', humanMetadata.decimals);
console.log(' Deposit:', humanMetadata.deposit);
console.log(' IsFrozen:', humanMetadata.isFrozen);
console.log('-----');
} catch (error) {
console.error(`Error fetching metadata for asset ${id}:`, error);
}
})
);
await api.disconnect();
} catch (error) {
console.error('Error in getXc20s:', error);
}
};
getXc20s().catch(console.error);
```
The result will display the asset ID along with some additional information for all of the registered external XC-20s.
## Retrieve Local XC-20 Metadata {: #retrieve-local-xc20-metadata }
Since local XC-20s are ERC-20s on Moonbeam that can be transferred via XCM to another parachain, you can interact with local XC-20s like you would an ERC-20. As long as you have the address and the ABI of the ERC-20, you can retrieve its metadata by interacting with its ERC-20 interface to retrieve the name, symbol, and decimals for the asset.
The following is an example that retrieves the asset metadata for the [Jupiter token](https://moonbase.moonscan.io/token/0x9aac6fb41773af877a2be73c99897f3ddfacf576){target=\_blank} on Moonbase Alpha:
=== "Ethers.js"
```js
import { ethers } from 'ethers';
const providerRPC = {
moonbase: {
name: 'moonbase',
rpc: 'https://rpc.api.moonbase.moonbeam.network', // Insert your RPC URL here
chainId: 1287, // 0x507 in hex,
},
};
const provider = new ethers.JsonRpcProvider(providerRPC.moonbase.rpc, {
chainId: providerRPC.moonbase.chainId,
name: providerRPC.moonbase.name,
});
// Replace with the address of the ERC-20 token
const tokenAddress = '0x9Aac6FB41773af877a2Be73c99897F3DdFACf576';
const tokenABI = [
'function name() view returns (string)',
'function symbol() view returns (string)',
'function decimals() view returns (uint8)',
];
const tokenContract = new ethers.Contract(tokenAddress, tokenABI, provider);
async function getTokenMetadata() {
try {
const [name, symbol, decimals] = await Promise.all([
tokenContract.name(),
tokenContract.symbol(),
tokenContract.decimals(),
]);
console.log(`Name: ${name}`);
console.log(`Symbol: ${symbol}`);
console.log(`Decimals: ${decimals}`);
} catch (error) {
console.error('Error fetching token metadata:', error);
}
}
getTokenMetadata();
```
=== "Web3.js"
```js
import { Web3 } from 'web3';
// Insert your RPC URL here
const web3 = new Web3('https://rpc.api.moonbase.moonbeam.network');
// Replace with the address of the ERC-20 token
const tokenAddress = '0x9Aac6FB41773af877a2Be73c99897F3DdFACf576';
const tokenABI = [
// ERC-20 ABI
{
constant: true,
inputs: [],
name: 'name',
outputs: [{ name: '', type: 'string' }],
payable: false,
stateMutability: 'view',
type: 'function',
},
{
constant: true,
inputs: [],
name: 'symbol',
outputs: [{ name: '', type: 'string' }],
payable: false,
stateMutability: 'view',
type: 'function',
},
{
constant: true,
inputs: [],
name: 'decimals',
outputs: [{ name: '', type: 'uint8' }],
payable: false,
stateMutability: 'view',
type: 'function',
},
];
const tokenContract = new web3.eth.Contract(tokenABI, tokenAddress);
async function getTokenMetadata() {
try {
const [name, symbol, decimals] = await Promise.all([
tokenContract.methods.name().call(),
tokenContract.methods.symbol().call(),
tokenContract.methods.decimals().call(),
]);
console.log(`Name: ${name}`);
console.log(`Symbol: ${symbol}`);
console.log(`Decimals: ${decimals}`);
} catch (error) {
console.error('Error fetching token metadata:', error);
}
}
getTokenMetadata();
```
=== "Web3.py"
```py
from web3 import Web3
web3 = Web3(Web3.HTTPProvider("https://rpc.api.moonbase.moonbeam.network"))
# Replace with the address of the ERC-20 token
token_address = "0x9Aac6FB41773af877a2Be73c99897F3DdFACf576"
token_abi = [ # ERC-20 ABI
{
"constant": True,
"inputs": [],
"name": "name",
"outputs": [{"name": "", "type": "string"}],
"payable": False,
"stateMutability": "view",
"type": "function",
},
{
"constant": True,
"inputs": [],
"name": "symbol",
"outputs": [{"name": "", "type": "string"}],
"payable": False,
"stateMutability": "view",
"type": "function",
},
{
"constant": True,
"inputs": [],
"name": "decimals",
"outputs": [{"name": "", "type": "uint8"}],
"payable": False,
"stateMutability": "view",
"type": "function",
},
]
token_contract = web3.eth.contract(address=token_address, abi=token_abi)
def get_token_metadata():
try:
name = token_contract.functions.name().call()
symbol = token_contract.functions.symbol().call()
decimals = token_contract.functions.decimals().call()
print(f"Name: {name}")
print(f"Symbol: {symbol}")
print(f"Decimals: {decimals}")
except Exception as e:
print(f"Error fetching token metadata: {e}")
get_token_metadata()
```
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/interoperability/xcm/xc20/send-xc20s/overview/
--- BEGIN CONTENT ---
---
title: XC-20 Transfers Overview
description: Explore the types of asset transfers and some of the fundamentals of remote asset transfers via XCM, including the XCM instructions for asset transfers.
categories: Basics, XC-20
---
# Overview of XC-20 Transfers
## Introduction {: #introduction }
Assets can move between parachains using XCM. Two main approaches exist:
- **Asset teleporting** – destroys tokens on the reserve chain and mints the same amount on the destination chain. Each chain holds the native asset as a reserve, similar to a burn-mint bridging mechanism. Because each chain can create tokens, a degree of trust is required
- **Remote transfers** – moves tokens from the reserve chain to a Sovereign account (an account on the reserve chain trustlessly controlled by the destination chain). The destination chain then mints a wrapped (also called “virtual” or “cross-chain”) representation. This wrapped version is always interchangeable 1:1 with the original asset, functioning like a lock-mint and burn-unlock bridge. The chain where the asset originates is known as the reserve chain

Moonbeam currently uses remote transfers for XC-20 transfers.
This page covers the fundamentals of XCM-based remote transfers. To learn how to perform XC-20 transfers, refer to the the [XC-20 transfers via the Substrate API](/builders/interoperability/xcm/xc20/send-xc20s/xcm-pallet/){target=\_blank} guide.
## XCM Instructions for Asset Transfers {: #xcm-instructions-for-asset-transfers }
The XCM Pallet and Precompile abstract much of the complexity involved in cross-chain asset transfers, automatically constructing the necessary XCM messages. Nevertheless, having a basic understanding of the underlying instructions can be useful.
For reference, you can find the Polkadot XCM Pallet extrinsics for sending XC-20s in the [Using the Polkadot XCM Pallet To Send XC-20s guide](/builders/interoperability/xcm/xc20/send-xc20s/xcm-pallet/){target=_blank}.
The instructions in each XCM transfer vary depending on the asset and the transfer route. For example, returning a native token like xcDOT to its reserve chain (from Moonbeam to Polkadot) differs from sending DOT from Polkadot to Moonbeam. Below are examples of the instructions commonly involved in these token transfers.
### Instructions to Transfer a Reserve Asset from the Reserve Chain {: #transfer-native-from-origin }
When DOT is transferred from Polkadot to Moonbeam, the following XCM instructions are executed in sequence:
1. [`TransferReserveAsset`](/builders/interoperability/xcm/core-concepts/instructions/#transfer-reserve-asset){target=_blank} - executes on Polkadot, moving the DOT from the sender and depositing it into Moonbeam’s Sovereign account on Polkadot
2. [`ReserveAssetDeposited`](/builders/interoperability/xcm/core-concepts/instructions/#reserve-asset-deposited){target=_blank} - executes on Moonbeam, minting the corresponding ERC-20 representation of DOT (xcDOT) on Moonbeam
3. [`ClearOrigin`](/builders/interoperability/xcm/core-concepts/instructions/#clear-origin){target=_blank} - executes on Moonbeam, clearing any origin data—previously set to Polkadot’s Sovereign account
4. [`BuyExecution`](/builders/interoperability/xcm/core-concepts/instructions/#buy-execution){target=_blank} - executes on Moonbeam, determining the execution fees. Here, a portion of the newly minted xcDOT is used to pay the cost of XCM
5. [`DepositAsset`](/builders/interoperability/xcm/core-concepts/instructions/#deposit-asset){target=_blank} - executes on Moonbeam, delivering the xcDOT to the intended recipient’s account on Moonbeam
This process invokes `TransferReserveAsset` with `assets`, `dest`, and `xcm`parameters. Within the `xcm` parameter, you typically specify the `BuyExecution` and `DepositAsset` instructions. As shown in the [`TransferReserveAsset` instruction](https://github.com/paritytech/polkadot-sdk/blob/{{ polkadot_sdk }}/polkadot/xcm/xcm-executor/src/lib.rs#L630){target=\_blank}, the flow also includes `ReserveAssetDeposited` and `ClearOrigin` to complete the transfer.
For more information on constructing an XCM message for asset transfers, such as DOT to Moonbeam, refer to the [Polkadot XCM Pallet guide](/builders/interoperability/xcm/xc20/send-xc20s/xcm-pallet/){target=\_blank}.
### Instructions to Transfer a Reserve Asset back to the Reserve Chain {: #transfer-native-to-origin }
In scenarios where you want to move an asset back to its reserve chain, such as sending xcDOT from Moonbeam to Polkadot, Moonbeam uses the following set of XCM instructions:
1. [`WithdrawAsset`](/builders/interoperability/xcm/core-concepts/instructions/#withdraw-asset){target=_blank} – executes on Moonbeam, taking the specified token (xcDOT) from the sender
2. [`InitiateReserveWithdraw`](/builders/interoperability/xcm/core-concepts/instructions/#initiate-reserve-withdraw){target=_blank} – executes on Moonbeam, which, burns the token on Moonbeam (removing the wrapped representation), and sends an XCM message to Polkadot, indicating the tokens should be released there
3. [`WithdrawAsset`](/builders/interoperability/xcm/core-concepts/instructions/#withdraw-asset){target=_blank} – executes on Polkadot, removing the tokens from Moonbeam’s Sovereign account on Polkadot
4. [`ClearOrigin`](/builders/interoperability/xcm/core-concepts/instructions/#clear-origin){target=_blank} – gets executed on Polkadot. Clears any origin data (e.g., the Sovereign account on Moonbeam)
5. [`BuyExecution`](/builders/interoperability/xcm/core-concepts/instructions/#buy-execution){target=_blank} – Polkadot determines the execution fees and uses part of the DOT being transferred to pay for them
6. [`DepositAsset`](/builders/interoperability/xcm/core-concepts/instructions/#deposit-asset){target=_blank} – finally, the native DOT tokens are deposited into the specified Polkadot account
Steps 3 through 6 are automatically triggered by the `InitiateReserveWithdraw` instruction (step 2) and execute on Polkadot. Once `InitiateReserveWithdraw` is invoked on Moonbeam, the assembled XCM message instructs Polkadot to run those final instructions, completing the cross-chain transfer. In other words, while Moonbeam constructs the XCM instructions behind the scenes, they ultimately execute on Polkadot to complete the asset’s return to its reserve chain.
For more information on constructing an XCM message to transfer reserve assets to a target chain, such as xcDOT to Polkadot, you refer to the guide to the [Polkadot XCM Pallet](/builders/interoperability/xcm/xc20/send-xc20s/xcm-pallet/){target=_blank}.
!!! note
The specific instructions may vary over time, but this overall flow remains consistent: the tokens are withdrawn from the user on Moonbeam, burned from the local representation, and unlocked on the reserve chain. At the end of the process, they become fully accessible again on their reserve chain.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/node-operators/networks/collators/overview/
--- BEGIN CONTENT ---
---
title: Run a Collator Node
description: Instructions on how to dive in and become a collator in the Moonbeam Network once you are running a node.
categories: Basics, Node Operators and Collators
---
# Run a Collator on Moonbeam
## Introduction {: #introduction }
Collators are members of the network that maintain the parachains they take part in. They run a full node (for both their particular parachain and the relay chain), and they produce the state transition proof for relay chain validators.
There are some [requirements](/node-operators/networks/collators/requirements/){target=\_blank} that need to be considered prior to becoming a collator candidate including machine, bonding, account, and community requirements.
Candidates will need a minimum amount of tokens bonded (self-bonded) to be considered eligible. Only a certain number of the top collator candidates by total stake, including self-bonded and delegated stake, will be in the active set of collators. Otherwise, the collator will remain in the candidate pool.
Once a candidate is selected to be in the active set of collators, they are eligible to produce blocks.
Moonbeam uses the [Nimbus Parachain Consensus Framework](/learn/features/consensus/){target=\_blank}. This provides a two-step filter to allocate candidates to the active set of collators, then assign collators to a block production slot:
- The parachain staking filter selects the top candidates in terms of tokens staked in each network. For the exact number of top candidates per each network and the minimum bond amount, you can check out the [Minimum Collator Bond](/node-operators/networks/collators/requirements/#minimum-collator-bond){target=\_blank} section of our documentation. This filtered pool is called selected candidates (also known as the active set), which are rotated every round
- The fixed size subset filter picks a pseudo-random subset of the previously selected candidates for each block production slot
Users can spin up full nodes on Moonbeam, Moonriver, and Moonbase Alpha and activate the `collate` feature to participate in the ecosystem as collator candidates. To do this, you can checkout the [Run a Node](/node-operators/networks/run-a-node/){target=\_blank} section of the documentation and spin up a node using either [Docker](/node-operators/networks/run-a-node/docker/){target=\_blank} or [Systemd](/node-operators/networks/run-a-node/systemd/){target=\_blank}.
## Join the Discord {: #join-discord }
As a collator, it is important to keep track of updates and changes to configuration. It is also important to be able to easily contact us and vice versa in case there is any issue with your node, as that will not only negatively affect collator and delegator rewards, it will also negatively affect the network.
For this purpose, we use [Discord](https://discord.com/invite/moonbeam){target=\_blank}. The most relevant Discord channels for collators are the following:
- **tech-upgrades-announcements** — here we will publish any updates or changes in configuration changes collators will be required to follow. We will also announce any technical issues to monitor, such as network stalls
- **collators** — this is the general collator discussion channel. We are proud of having an active and friendly collator community so if you have any questions, this is the place to ask. We will also ping collators here for any issues that require their attention.
- **meet-the-collators** — in this channel you can introduce yourself to potential delegators
After you join our Discord, feel free to DM *gilmouta* or *artkaseman* and introduce yourself. This will let us know who to contact if we see an issue with your node, and will also let us assign the relevant Discord collator role, enabling you to post in *meet-the-collators*.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/node-operators/networks/run-a-node/overview/
--- BEGIN CONTENT ---
---
title: Run a Node
description: Learn about all of the necessary details to run a full parachain node for the Moonbeam Network to have your RPC endpoint or produce blocks.
categories: Basics, Node Operators and Collators
---
# Run a Node on Moonbeam
## Introduction {: #introduction }
Running a full node on a Moonbeam-based network allows you to connect to the network, sync with a bootnode, obtain local access to RPC endpoints, author blocks on the parachain, and more.
There are multiple deployments of Moonbeam, including the Moonbase Alpha TestNet, Moonriver on Kusama, and Moonbeam on Polkadot. Here's how these environments are named and their corresponding [chain specification file](https://docs.polkadot.com/develop/parachains/deployment/generate-chain-specs/) names:
| Network | Hosted By | Chain Name |
|:--------------:|:-------------------:|:-----------------------------------:|
| Moonbase Alpha | Moonbeam Foundation | {{ networks.moonbase.chain_spec }} |
| Moonriver | Kusama | {{ networks.moonriver.chain_spec }} |
| Moonbeam | Polkadot | {{ networks.moonbeam.chain_spec }} |
!!! note
Moonbase Alpha is still considered an Alphanet, and as such _will not_ have 100% uptime. The parachain might be purged as needed. During the development of your application, make sure you implement a method to redeploy your contracts and accounts to a fresh parachain quickly. If a chain purge is required, it will be announced via our [Discord channel](https://discord.com/invite/PfpUATX) at least 24 hours in advance.
## Requirements {: #requirements }
Running a parachain node is similar to a typical Substrate node, but there are some differences. A Substrate parachain node is a bigger build because it contains code to run the parachain itself, as well as code to sync the relay chain and facilitate communication between the two. As such, this build is quite large and may take over 30 min and require 32GB of memory.
The minimum specs recommended to run a node are shown in the following table. For our Kusama and Polkadot MainNet deployments, disk requirements will be higher as the network grows.
=== "Moonbeam"
| Component | Requirement |
|:------------:|:--------------------------------------------------------------------------------------------------------------------------:|
| **CPU** | {{ networks.moonbeam.node.cores }} Cores (Fastest per core speed) |
| **RAM** | {{ networks.moonbeam.node.ram }} GB |
| **SSD** | {{ networks.moonbeam.node.hd }} TB (recommended) |
| **Firewall** | P2P port must be open to incoming traffic: - Source: Any - Destination: 30333, 30334 TCP |
=== "Moonriver"
| Component | Requirement |
|:------------:|:--------------------------------------------------------------------------------------------------------------------------:|
| **CPU** | {{ networks.moonriver.node.cores }} Cores (Fastest per core speed) |
| **RAM** | {{ networks.moonriver.node.ram }} GB |
| **SSD** | {{ networks.moonriver.node.hd }} TB (recommended) |
| **Firewall** | P2P port must be open to incoming traffic: - Source: Any - Destination: 30333, 30334 TCP |
=== "Moonbase Alpha"
| Component | Requirement |
|:------------:|:--------------------------------------------------------------------------------------------------------------------------:|
| **CPU** | {{ networks.moonbase.node.cores }} Cores (Fastest per core speed) |
| **RAM** | {{ networks.moonbase.node.ram }} GB |
| **SSD** | {{ networks.moonbase.node.hd }} TB (recommended) |
| **Firewall** | P2P port must be open to incoming traffic: - Source: Any - Destination: 30333, 30334 TCP |
!!! note
If you don't see an `Imported` message (without the `[Relaychain]` tag) when running a node, you might need to double-check your port configuration.
## Running Ports {: #running-ports }
As stated before, the relay/parachain nodes will listen on multiple ports. The default Substrate ports are used in the parachain, while the relay chain will listen on the next higher port.
The only ports that need to be open for incoming traffic are those designated for P2P. **Collators must not have RPC or WS ports opened**.
!!! note
As of client v0.33.0, the `--ws-port` and `--ws-max-connections` flags have been deprecated and removed in favor of the `--rpc-port` and `--rpc-max-connections` flags for both RPC and WSS connections. The default port is `9944`, and the default maximum number of connections is set to 100.
### Default Ports for a Parachain Full-Node {: #default-ports-for-a-parachain-full-node }
| Description | Port |
|:--------------:|:-----------------------------------:|
| **P2P** | {{ networks.parachain.p2p }} (TCP) |
| **RPC & WS** | {{ networks.parachain.ws }} |
| **Prometheus** | {{ networks.parachain.prometheus }} |
### Default Ports of Embedded Relay Chain {: #default-ports-of-embedded-relay-chain }
| Description | Port |
|:--------------:|:-------------------------------------:|
| **P2P** | {{ networks.relay_chain.p2p }} (TCP) |
| **RPC & WS** | {{ networks.relay_chain.ws }} |
| **Prometheus** | {{ networks.relay_chain.prometheus }} |
## Installation {: #installation }
There are a couple different guides to help you get started running a Moonbeam-based node:
- [Using Docker](/node-operators/networks/run-a-node/docker/) - this method provides a quick and easy way to get started with a Docker container
- [Using Systemd](/node-operators/networks/run-a-node/systemd/) - this method is recommended for those with experience compiling a Substrate node
## Debug, Trace and TxPool APIs {: #debug-trace-txpool-apis }
You can also gain access to some non-standard RPC methods by running a tracing node, which allow developers to inspect and debug transactions during runtime. Tracing nodes use a different Docker image than a standard Moonbase Alpha, Moonriver, or Moonbeam node. Check out the [Run a Tracing Node](/node-operators/networks/tracing-node/) guide and be sure to switch to the right network tab throughout the instructions. Then to interact with your tracing node, check out the [Debug & Trace](/builders/ethereum/json-rpc/debug-trace/) guide.
## Lazy Loading {: #lazy-loading }
Lazy loading lets a Moonbeam node operate while downloading network state in the background, eliminating the need to wait for full synchronization before use. You can activate lazy loading with the following flag:
- **`--lazy-loading-remote-rpc`** - allows lazy loading by relying on a specified RPC for network state until the node is fully synchronized e.g. `--lazy-loading-remote-rpc 'INSERT-RPC-URL'`
Upon spooling up a node with this feature, you'll see output like the following:
[Lazy loading 🌗]
You are now running the Moonbeam client in lazy loading mode, where data is retrieved
from a live RPC node on demand.
Using remote state from: https://moonbeam.unitedbloc.com
Forking from block: 8482853
To ensure the client works properly, please note the following:
1. *Avoid Throttling*: Ensure that the backing RPC node is not limiting the number of
requests, as this can prevent the lazy loading client from functioning correctly;
2. *Be Patient*: As the client may take approximately 20 times longer than normal to
retrieve and process the necessary data for the requested operation.
The service will start in 10 seconds...
!!! note
Lazy loading a Moonbeam requires a large number of RPC requests. To avoid being rate-limited by a public endpoint, it's highly recommended to use a [dedicated endpoint](/builders/get-started/endpoints#endpoint-providers).
You can further customize your use of the lazy loading functionality with the following optional parameters:
- **`--lazy-loading-block`** - specifies a block hash from which to start loading data. If not provided, the latest block will be used
- **`--lazy-loading-delay-between-requests`** - the delay (in milliseconds) between RPC requests when using lazy loading. This parameter controls the amount of time to wait between consecutive RPC requests. This can help manage request rate and avoid overwhelming the server. Default value is `100` milliseconds
- **`--lazy-loading-max-retries-per-request`** - the maximum number of retries for an RPC request when using lazy loading. Default value is `10` retries
- **`--lazy-loading-runtime-override`** - path to a WASM file to override the runtime when forking. If not provided, it will fetch the runtime from the block being forked
- **`--lazy-loading-state-overrides`** - path to a JSON file containing state overrides to be applied when forking
The state overrides file should define the respective pallet, storage item, and value that you seek to override as follows:
```json
[
{
"pallet": "System",
"storage": "SelectedCandidates",
"value": "0x04f24ff3a9cf04c71dbc94d0b566f7a27b94566cac"
}
]
```
## Logs and Troubleshooting {: #logs-and-troubleshooting }
You will see logs from both the relay chain and the parachain. The relay chain will be prefixed by `[Relaychain]`, while the parachain has no prefix.
### P2P Ports Not Open {: #p2p-ports-not-open }
If you don't see an `Imported` message (without the `[Relaychain]` tag), you need to check the P2P port configuration. P2P port must be open to incoming traffic.
### In Sync {: #in-sync }
Both chains must be in sync at all times, and you should see either `Imported` or `Idle` messages and have connected peers.
### Genesis Mismatching {: #genesis-mismatching }
The Moonbase Alpha TestNet may need to be purged and upgraded once in a while. Consequently, you may see the following message:
```text
DATE [Relaychain] Bootnode with peer id `ID` is on a different
chain (our genesis: GENESIS_ID theirs: OTHER_GENESIS_ID)
```
This typically means that you are running an older version and will need to upgrade.
We announce the upgrades (and corresponding chain purge) via our [Discord channel](https://discord.com/invite/PfpUATX) at least 24 hours in advance.
Instructions for purging chain data will vary slightly depending on how you spun up your node:
- For Docker, you can check out the [Purge Your Node](/node-operators/networks/run-a-node/docker/#purge-your-node) section of the [Using Docker](/node-operators/networks/run-a-node/docker/) page
- For Systemd, you can take a look at the [Purge Your Node](/node-operators/networks/run-a-node/systemd/#purge-your-node) section of the [Using Systemd](/node-operators/networks/run-a-node/systemd/) page
--- END CONTENT ---
## Reference Concepts [shared: true]
The following section contains reference material for Moonbeam.
It includes network endpoints, JSON-RPC methods, and contract or token addresses.
While it may not be required for all use cases, it offers a deeper technical layer for advanced development work.
---
## List of shared concept pages:
## Full content for shared concepts:
Doc-Content: https://docs.moonbeam.network/learn/dapp-directory/
--- BEGIN CONTENT ---
---
title: List your Dapp on the Moonbeam DApp Directory
description: Follow this tutorial to learn how to list your Moonbeam or Moonriver project or update a current listing on the Moonbeam Foundation DApp Directory.
dropdown_description: Explore the DApp Directory and listing process
categories: Reference
---
# How to List your Project on the Moonbeam DApp Directory
## Introduction to the Moonbeam DApp Directory {: #introduction-to-state-of-the-dapps }
The Moonbeam ecosystem comprises two distinct production networks: Moonbeam and Moonriver. Each network has its own dedicated [DApp Directory](https://apps.moonbeam.network/moonbeam/app-dir){target=\_blank}, maintained by the Moonbeam Foundation. These directories categorize projects spanning from DeFi to NFTs to gaming, providing users with comprehensive access to diverse applications.
You'll supply core project details like name, description, and relevant links when adding your project. Depending on your project type, you may include additional data such as on-chain stats and token information.
Despite the distinction between the Moonbeam and Moonriver DApp directories, the submission process remains the same. To list your project on the DApp Directory, you must submit a pull request to the [Moonbeam Foundation's App Directory Data repository on GitHub](https://github.com/moonbeam-foundation/app-directory-data){target=\_blank}. This guide outlines the necessary data and formatting specifics for your submission.

## Overview of the Project Data {: #overview-project-data }
There are four main sources of data that are used for a project's listing in the Moonbeam DApp Directory:
- **Core Project Data** - core project data such as descriptions, logos, and screenshots. This data also includes IDs used to query data from external platforms
- **Active Users and Transaction Volume** - on-chain data based on smart contract activity for all of the contracts associated with the project. Data is discovered via the use of contract labeling in Moonscan, which is then indexed by Web3Go and consumed by the DApp Directory
- **TVL Data** - TVL data for the protocol, sourced from the project's listing on DefiLlama
- **Project Token Information** - token information, which is sourced from the project's listing on CoinGecko
## Prerequisites for Using External Data Sources {: #configuring-external-data-sources }
Before pulling data from the mentioned sources, certain prerequisites must be fulfilled. However, it's worth noting that these steps may not apply to all project types. For instance, in the case of wallets, where there are no smart contracts, the DApp Directory is currently unable to display user and transaction activity data.
### Configure the Data Source for Active Users and Transaction Volume {: #configure-active-users }
For projects that have smart contracts deployed on Moonbeam or Moonriver, it is important that those contracts can be linked to the DApp Directory project data.
The end-to-end flow for linking smart contract activity to the DApp Directory is as follows:
1. The smart contract owner fills in the [form to label contracts on Moonscan](https://moonscan.io/contactus?id=5){target=\_blank}
2. The contracts become labeled in Moonscan
3. Periodically, the entire list of labeled contracts is exported and transmitted to Web3Go to be ingested
4. Every hour, Web3Go loads smart contract activity within Moonbeam and Moonriver and runs a job to index this data by the labels
To get your project's smart contracts properly labeled on [Moonscan](https://moonscan.io){target=\_blank}, please refer to Web3Go's documentation on the [Labeling Structure](https://dinlol.gitbook.io/moonscan-smart-contract-label-for-projects/labeling-structure){target=\_blank} and [How to Submit Contract Information](https://dinlol.gitbook.io/moonscan-smart-contract-label-for-projects/how-to-submit-contract-information){target=\_blank} on Moonscan.
Once you've labeled your smart contracts and are ready to submit your project to the DApp Directory, configuring the Directory to utilize your smart contract data becomes straightforward. You'll only need the **Project** component of your labeled contracts.
Consider the following example project with two smart contracts: a Comptroller and a Router recently updated to a new version.
| Project | Contract Name | Contract Version | Resulting Label |
|:----------:|:-------------:|:----------------:|:--------------------------:|
| My Project | Comptroller | V1 | My Project: Comptroller V1 |
| My Project | Router | V2 | My Project: Router V2 |
To submit your project to the Moonbeam DApp Directory, ensure you have your **Project** name ready, identified here as `My Project`.
If you're ready to add your project to the DApp Directory, skip to the [How to Submit Your Project Listing](#how-to-submit-your-project-listing) section.
### Configure the Data Source for TVL {: #configure-tvl }
If the project represents a DeFi protocol with TVL (whereby value is locked in the protocol's smart contract), it is possible to display TVL in the Moonbeam DApp Directory.
TVL data is pulled from [DefiLlama](https://defillama.com){target=\_blank}, so you must list your project there. To get your project listed, please refer to DefiLlama's documentation on [How to list a DeFi project](https://docs.llama.fi/list-your-project/submit-a-project){target=\_blank}.
After listing your project, you can easily configure the DApp Directory to pull data from DefiLlama. To do so, you'll need the DefiLlama identifier, which you can find in the URL for your protocol's page. For example, the URL for Moonwell's page is `https://defillama.com/protocol/moonwell`, so the identifier is `moonwell`.
If you have the identifier and are ready to submit your project to the Moonbeam DApp Directory, skip to the [How to Submit Your Project Listing](#how-to-submit-your-project-listing) section.
### Configure the Data Source for Project Token Information {: #project-token-information }
If a project has a token, it is possible to display the name of the token, current price, and contract in the DApp Directory.
However, the data is pulled from [CoinGecko](https://www.coingecko.com){target=\_blank}, so the project's token must be listed there. If your token is not listed there, you can complete [CoinGecko's Request Form](https://support.coingecko.com/hc/en-us/requests/new){target=\_blank} to initiate the listing process.
Assuming your project's token is listed there, you must obtain the CoinGecko **API ID** value. You can find the **API ID** value in the **Information** section of the token's page on CoinGecko. For example, the **API ID** on [Moonwell's token page](https://www.coingecko.com/en/coins/moonwell){target=\_blank} is `moonwell-artemis`.
If you have the CoinGecko ID and are ready to submit your project to the Moonbeam DApp Directory, you can continue to the next section.
## How to Submit Your Project Listing {: #how-to-submit-your-project-listing }
As mentioned, you must submit a pull request to the Moonbeam Foundation's GitHub repository that holds the DApp Directory's data. Before getting started, it's worth noting that to expedite the review process, the GitHub user who submits the pull request is recommended to be a major contributor to the project's GitHub so that the Moonbeam Foundation can quickly verify that they represent the project. You can check out the [Review Process](#review-process) section for more information.
To begin, you have two options for adding your project information to the [`app-directory-data` repository on GitHub](https://github.com/moonbeam-foundation/app-directory-data){targe\_blank}. You can utilize [GitHub's browser-based editor](https://github.dev/moonbeam-foundation/app-directory-data){target=\_blank}, which offers a user-friendly interface.

Or you can clone the repository locally and make modifications using your preferred code editor, in which you can use the following command to clone the repository:
```bash
git clone https://github.com/moonbeam-foundation/app-directory-data.git
```
Once you've cloned the project, you can create a new branch to which you will add all of your changes. To do this on the browser-based editor, take the following steps:
1. Click on the current branch name in the bottom left corner
2. A menu will appear at the top of the page. Enter the name of your branch
3. Click **Create new branch...**

The page will reload, and your branch name will now be displayed in the bottom left corner.
### Projects with Deployments on Moonbeam and Moonriver {: #projects-with-deployments }
If a project is deployed to both Moonbeam and Moonriver, there are two different options available:
- Create a separate project structure for each deployment
- Use a single project structure and modify the project data file for both projects
Separate project structures should be used if:
- The two deployments have distinct representations in DefiLlama (i.e., two distinct identifiers)
- The project has two different tokens, one native to Moonbeam and one native to Moonriver
Otherwise, either option may be used.
### Set Up the Folder Structure for Your Project {: #set-up-the-file-structure }
All configurations for each project listed in the DApp Directory are stored in the `projects` folder.
To get started, you must have a name that uniquely and properly identifies your project. Using your project name, you can take the following steps:
1. Create a new directory for your project using your unique project name
2. In your project directory, you'll need to create:
1. A project data file is a JSON file that defines all your project data and contains references to the images stored in the `logos` and `screenshots` folders. The list of fields you can use to define your data, with descriptions, is outlined in the next section. The file must be named using your unique project name
2. A `logos` folder where your project logo images are stored
3. (Optional) A `screenshots` folder where screenshots for the project are stored
??? code "Example folder structure"
```text
my-project
├── my-project.json
├── logos
│ ├── my-project-logo-small.jpeg
│ └── my-project-logo-full.jpeg
└── screenshots
├── my-project-screenshot1-small.jpeg
├── my-project-screenshot1-full.jpeg
├── my-project-screenshot2-small.jpeg
└── my-project-screenshot2-full.jpeg
```

With the foundational file structure in place, you're ready to populate the necessary information for your project submission.
### Add Information to the Project Data File {: #add-information }
Your project's data file is where you'll add all the information for your project. The file permits the following top-level properties:
|
Property
| Type | Description |
|:--------------------------------------:|:-----------------------------------------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
| `id` | String | Unique identifier for the dApp in the Moonbeam DApp Directory. It should be a unique, human-readable string representing this project. E.g., `my-project` |
| `slug` | String | Identifier used in certain third-party sources. In particular, if the project is listed in DefiLlama, this value should be set to the DefiLlama identifier. See the [Configure the Data Source for TVL](#configure-tvl) section for more information |
| `name` | String | The project name as it will appear in the DApp Directory. E.g., `My Project` |
| `category` | String | The category the project should be associated with. A project can only have one category, and it corresponds to the category list in the left-hand nav of the DApp Directory. See the [Category and Tags](#category-and-tags) section for the accepted list of values |
| `coinGeckoId` | String | If the project has a token listed on CoinGecko, this property should have the **API ID** value corresponding to the given token. See the [Configure the Data Source for Project Token Information](#project-token-information) section for more information |
| `chains` | Array of Strings | List of Moonbeam ecosystem chains on which the project is deployed. Valid values are currently `moonbeam` and `moonriver` |
| `web3goIDs` | Array of Strings | List of Web3Go identifiers for a given dApp. The identifiers should correspond to the **Project** component of the smart contract labels set up in Moonscan. Generally, there should only be one value in the array. See the [Configure the Data Source for Active Users and Transaction Volume](#configure-active-users) section for more information |
| `logo` | Map of Strings to JSON objects | Map of logo image files associated with this project and stored in the `logos` directory. See the [Logos](#logos) section for more information |
| `shortDescription` | String | A short description of the project used in the display card when browsing dapps in the directory. This should be kept to under 80 characters |
| `description` | String | A longer description used in the project detail page. Markdown or similar formatting cannot be used. Line breaks can be used using `\r\n`. The text should be limited to a few paragraphs |
| `tags` | Array of Strings | A list of applicable [tags](#category-and-tags) for this project. Tag values will show up in the project details. See the [Category and Tags](#category-and-tags) section for the accepted list of values |
| `contracts` | Array of contract JSON objects | List of contracts for the project. Currently, this is used only for token contracts. The list of smart contracts which make up the protocol is externally sourced from Moonscan. See the [Contracts](#contracts) section for more information |
| `urls` | Map of Strings (names) to Strings (URLs) | Mapping of URLs for websites and socials associated with the project. See the [URLs](#urls) section for the accepted list of properties |
| `screenshots` | Array of Maps of Strings (size) to image JSON objects | List of screenshot image files associated with this project and stored in the `screenshots` directory. See the [Screenshots](#screenshots) section for more information |
| `projectCreationDate` | int | The date the project was created. Used for sorting purposes in the DApp Directory |
??? code "Example project data file"
```json
{
"id": "moonwell",
"slug": "moonwell",
"name": "Moonwell",
"category": "lending",
"coinGeckoId": "moonwell-artemis",
"chains": [
"moonbeam"
],
"web3goIDs": [
"Moonwell Artemis"
],
"logo": {
"small": {
"fileName": "moonwell-logo-small.jpeg",
"width": 40,
"height": 40,
"mimeType": "image/jpeg"
},
"large": {
"fileName": "moonwell-logo-large.jpeg",
"width": 400,
"height": 400,
"mimeType": "image/jpeg"
},
"full": {
"fileName": "moonwell-logo-full.jpeg",
"width": 3000,
"height": 3000,
"mimeType": "image/jpeg"
}
},
"shortDescription": "Lending, borrowing, and DeFi protocol built on Moonbeam and Moonriver",
"description": "Moonwell is an open lending, borrowing, and decentralized finance protocol built on Moonbeam and Moonriver. Moonwell’s composable design can accommodate a full range of DeFi applications in the greater Polkadot and Kusama (DotSama) ecosystem.\r\n\r\nOur first deployment will be on Kusama’s Moonriver, the sister network of Polkadot’s Moonbeam. Moonriver is where new products are expected to be incubated and developed prior to being deployed on Moonbeam.",
"tags": [
"Lending",
"DeFi"
],
"contracts": [
{
"contract": "0x511ab53f793683763e5a8829738301368a2411e3",
"chain": "moonbeam",
"name": "WELL Token"
}
],
"urls": {
"website": "https://moonwell.fi/",
"try": "https://moonwell.fi/",
"twitter": "https://twitter.com/MoonwellDeFi",
"medium": "https://moonwell.medium.com/",
"telegram": "https://t.me/moonwellfichat",
"github": "https://github.com/moonwell-open-source",
"discord": "https://discord.gg/moonwellfi"
},
"screenshots": [
{
"small": {
"fileName": "moonwell-screenshot-small1.png",
"width": 429,
"height": 200,
"mimeType": "image/png"
},
"full": {
"fileName": "moonwell-screenshot-full1.png",
"width": 514,
"height": 300,
"mimeType": "image/png"
}
},
{
"small": {
"fileName": "moonwell-screenshot-small2.png",
"width": 429,
"height": 200,
"mimeType": "image/png"
},
"full": {
"fileName": "moonwell-screenshot-full2.png",
"width": 1716,
"height": 800,
"mimeType": "image/png"
}
},
{
"small": {
"fileName": "moonwell-screenshot-small3.png",
"width": 429,
"height": 200,
"mimeType": "image/png"
},
"full": {
"fileName": "moonwell-screenshot-full3.png",
"width": 1054,
"height": 637,
"mimeType": "image/png"
}
},
{
"small": {
"fileName": "moonwell-screenshot-small4.png",
"width": 429,
"height": 200,
"mimeType": "image/png"
},
"full": {
"fileName": "moonwell-screenshot-full4.png",
"width": 1365,
"height": 436,
"mimeType": "image/png"
}
}
],
"projectCreationDate": 1644828523000
}
```
#### Category and Tags {: #category-and-tags }
A category is the primary classification for a project. A project can be categorized under only one category, but it can have multiple tags. Ensure you carefully select the most applicable category for your project to ensure it is easily found. Any secondary classifications can be included as a tag.
The currently supported values for `category` are:
```text
- Bridges
- DAO
- DEX
- DeFi
- Gaming
- Lending
- NFTs
- Other
- Social
- Wallets
```
The currently supported values for `tag` are:
```text
- Bridges
- DAO
- DEX
- DeFi
- DePIN
- Developer Tools
- Explorers
- Files
- GLMR Grants
- Gaming
- Infrastructure
- IoT
- Lending
- MOVR Grants
- Messaging
- NFT
- NFT Marketplaces
- On-ramp
- Other
- Social
- Tool
- VPN
- Wallets
- ZeroTrust
```
#### URLs {: #urls }
The `urls` property name/value pairs are used so a project can provide links to their website, socials, etc.
The following table lists the supported `urls` properties:
| Property Name | Description | Example |
|:-------------:|:------------------------------------------------------------------------------------------------------------------:|:-----------------------------------------------:|
| `website` | The main website for the project | https://moonbeam.network/ |
| `try` | URL a user should visit if they want to try out the dApp. Typically, this page will have a link to launch the dApp | https://moonbeam.network/ |
| `twitter` | The project's Twitter profile | https://twitter.com/MoonbeamNetwork |
| `medium` | The project's Medium site | https://medium.com/moonbeam-network |
| `telegram` | The project's Telegram | https://t.me/Moonbeam_Official |
| `github` | The project's GitHub repository | https://github.com/moonbeam-foundation/moonbeam |
| `discord` | The project's Discord | https://discord.com/invite/PfpUATX |
The format of the property name/value pairs should follow the JSON standard, for example:
```json
"urls": {
"website": "https://moonbeam.network/",
"try": "https://docs.moonbeam.network/",
"twitter": "https://twitter.com/MoonbeamNetwork"
}
```
#### Logos {: #logos }
The `logos` property of the main project data file is a map of image sizes (i.e., `small`, `large`, `full`) to corresponding image JSON objects. The image JSON object contains the display properties for the given image.
The following table lists the properties of the image JSON object:
| Property | Type | Description |
|:----------:|:------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------:|
| `fileName` | String | The name of the image file (unqualified) stored in the `logos` directory |
| `width` | int | The width of the logo image in pixels |
| `height` | int | The height of the logo image in pixels |
| `mimeType` | String | The standard [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types){target=\_blank} of the file. E.g., `"image/jpeg"` |
Currently, only the `small` size is utilized, and the dimensions for small logos should be 40x40 pixels.
Here is an example showing the structure of the `logo` property that supplies `small` and `full` logos:
```json
"logo": {
"small": {
"fileName": "my-project-logo-small.jpeg",
"width": 40,
"height": 40,
"mimeType": "image/jpeg"
},
"full": {
"fileName": "my-project-logo-full.jpeg",
"width": 3000,
"height": 3000,
"mimeType": "image/jpeg"
}
}
```
#### Screenshots {: #screenshots }
The `screenshots` property of the main project data file is an array of maps. Each map in the array is for a specific screenshot.
However, different-sized images for each screenshot should be supplied so that different sizes can be used in different contexts (e.g., thumbnails vs full-sized images). Thus, for each screenshot, there is a map of image sizes (i.e., `small`, `large`, `full`) to corresponding image JSON objects. The image JSON object contains the display properties for the given image.
The following table lists the properties of the image JSON object:
| Property | Type | Description |
|:----------:|:------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------:|
| `fileName` | String | The name of the image file (unqualified) stored in the `screenshots` directory |
| `width` | int | The width of the logo image in pixels |
| `height` | int | The height of the logo image in pixels |
| `mimeType` | String | The standard [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types){target=\_blank} of the file. E.g., `"image/jpeg"` |
Here is an example showing the structure of the `screenshot` property for two screenshots (`screenshot1` and `screenshot2`):
```json
"screenshots": [
{
"small": {
"fileName": "my-project-screenshot1-small.png",
"width": 429,
"height": 200,
"mimeType": "image/png"
},
"full": {
"fileName": "my-project-screenshot1-full.png",
"width": 514,
"height": 300,
"mimeType": "image/png"
}
},
{
"small": {
"fileName": "my-project-screenshot2-small.png",
"width": 429,
"height": 200,
"mimeType": "image/png"
},
"full": {
"fileName": "my-project-screenshot2-full.png",
"width": 1716,
"height": 800,
"mimeType": "image/png"
}
}
]
```
#### Contracts {: #contracts }
A list of contracts for the project. Currently, this is used only for token contracts.
The smart contracts that make up the protocol are sourced from [Moonscan](https://moonscan.io){target=\_blank} based on tagging, so they do not need to be listed here. If you have not properly labeled your contracts or are unsure if they are labeled according to the Moonbeam community standard, please refer to the [Configure the Data Source for Active Users and Transaction Volume](#configure-active-users) section.
The following table lists the properties found in the contract JSON object:
| Property | Type | Description |
|:----------:|:------:|:-----------------------------------------------------------------------------:|
| `contract` | String | The address for the smart contract |
| `chain` | String | The chain on which the contract is deployed (i.e., `moonbeam` or `moonriver`) |
| `name` | String | The name of the contract |
Here is a `contracts` array with a single smart contract for the WGLMR token:
```json
"contracts": [
{
"contract": "0xAcc15dC74880C9944775448304B263D191c6077F",
"chain": "moonbeam",
"name": "Wrapped GLMR Token"
}
]
```
### Submit a Pull Request {: #submit-a-pull-request }
After you've populated the project data file and added your logos and screenshots, you should be ready to submit your pull request.

From the web-based editor, take the following steps to commit your changes to the `app-directory-data` repository:
1. Click on the **Source Control** tab, which should show you how many pages have been added or changed
2. Review the files under the **Changes** section. Click the **+** button next to **Changes**, or as you review each file, click the **+** button next to the file name to add them to the list of **Staged Changes**

All of your files should now be under the **Staged Changes** section. All you have to commit and push the changes are:
1. Enter a descriptive commit message, such as "Add My Project", making sure to use your actual project name
2. Click **Commit & Push**

Now that you've committed the changes, you'll need to head over to the [`app-directory-data` repository](https://github.com/moonbeam-foundation/app-directory-data){target=\_blank} and open a pull request against the `develop` branch:
1. At the top of the repository page, click **Compare and Pull** button displayed on the banner, or
2. If the banner is not there anymore, you'll need to select your branch from the branches dropdown
3. Click the **Contribute** dropdown
4. Click the **Open pull request** button

You'll be taken to the **Comparing changes** page, where you'll need to:
1. Make sure that you are merging your branch into the `develop` branch, which is the **base** branch
2. Add a title
3. Add a description of the changes
4. Click **Create pull request**

### The Review Process {: #review-process }
Submitted pull requests will be reviewed bi-weekly by the Moonbeam Foundation. During the review, and especially for new projects, the Foundation may have to verify that the GitHub user who created the pull request is a contributor and/or represents the specific project. One way projects can expedite this process is if the submitter's GitHub account is also a major contributor to the project itself on GitHub. Alternatively, teams should leave a note in the pull request comments indicating how we can get in touch with project team members to verify.
A comment will be added to the pull request if any changes are requested. After your pull request has been approved, it will be merged, and your project will be added to the Moonbeam DApp Directory!
## How to Update Your Project Listing {: #how-to-update-your-project-listing }
As your project evolves, you may need to update your project's listing or images related to your listing. You can create a new branch for your changes, find and modify your existing project's data from the root `projects` directory, and make the desired changes.
If you are no longer using a logo or screenshot, please remember to remove it from the `logos` or `screenshots` directory.
Once your changes have been made, you must follow the same instructions in the [Submit a Pull Request](#submit-a-pull-request) section so the changes can be [reviewed](#review-process) by the Moonbeam Foundation. Please note that pull requests are reviewed on a bi-weekly basis, so if the update is urgent, you can create a [forum post](https://forum.moonbeam.network){target=\_blank} asking for assistance.
## DApp Directory API {: #dapp-directory-api }
The DApp Directory also features a queryable API that you can use to integrate data from Moonbeam's DApp Directory into your application. The API is public and currently does not require authentication. The base URL for the API is as follows:
```bash
https://apps.moonbeam.network/api/ds/v1/app-dir/
```
### Query a Project {: #query-a-project}
You can retrieve all the information for a particular project by appending `/projects/INSERT_PROJECT_NAME` to the base URL. If you need clarification on the project name, you can omit the project name as shown below to retrieve data for every listed project and find the project in the response.
```bash
https://apps.moonbeam.network/api/ds/v1/app-dir/projects
```
Here's an example of querying the API for StellaSwap, which returns the project description, social media information, user counts, relevant smart contract addresses, market data, images, and more.
```bash
https://apps.moonbeam.network/api/ds/v1/app-dir/projects/stellaswap
```
You can visit the query URL directory in the browser, using a tool like Postman, or directly from the command line with Curl as follows:
```bash
curl -H "Content-Type: application/json" -X GET 'https://apps.moonbeam.network/api/ds/v1/app-dir/projects/stellaswap'
```
??? code "API Response to Querying StellaSwap"
```json
{
"project":{
"currentTx":{
"moonbeam":2883079
},
"web3goIDs":[
"StellaSwap"
],
"name":"StellaSwap",
"currentTVL":{
"moonbeam":5046832.23328
},
"currentUsers":{
"moonbeam":52455
},
"coinGeckoId":"stellaswap",
"shortDescription":"The leading DEX and DeFi gateway on Moonbeam",
"id":"stellaswap",
"featured":true,
"tags":[
"DEX",
"DeFi"
],
"tvlChange7d":{
"moonbeam":-1.61482567543498
},
"urls":{
"telegram":"https://t.me/stellaswap",
"website":"https://stellaswap.com/",
"try":"https://stellaswap.com/",
"twitter":"https://twitter.com/StellaSwap",
"github":"https://github.com/stellaswap",
"medium":"https://stellaswap.medium.com/"
},
"web3goContracts":[
{
"name":"StellaSwap: stDOT Oracle Master",
"chain":"moonbeam",
"contract":"0x3b23f0675ffc45153eca239664ccaefc5e816b9c"
},
{
"name":"StellaSwap: stDOT Token",
"chain":"moonbeam",
"contract":"0xbc7e02c4178a7df7d3e564323a5c359dc96c4db4"
},
{
"name":"StellaSwap: stDOT Controller",
"chain":"moonbeam",
"contract":"0x002d34d6a1b4a8e665fec43fd5d923f4d7cd254f"
},
{
"name":"StellaSwap: stDOT Proxy Admin",
"chain":"moonbeam",
"contract":"0xe8a5c0039226269313c89c093a6c3524c4d39fa4"
},
{
"name":"StellaSwap: madUSDC GLMR V2",
"chain":"moonbeam",
"contract":"0x2ad0e92461df950e2b1c72e2f7a865c81eaa3ce6"
},
{
"name":"StellaSwap: Dual ETH - GLMR Rewarder V1",
"chain":"moonbeam",
"contract":"0x2ba130297d1966e077c2fb5e4b434e8802925277"
},
{
"name":"StellaSwap: BCMC Rewarder V1",
"chain":"moonbeam",
"contract":"0x18e75887aa81e113636e18d5a78e3ff93787ec88"
},
{
"name":"StellaSwap: Pulsar Position Manager V1",
"chain":"moonbeam",
"contract":"0x1ff2adaa387dd27c22b31086e658108588eda03a"
},
{
"name":"StellaSwap: DualETH Pool LP Token V1",
"chain":"moonbeam",
"contract":"0xa3ee3a0a36dc915fdc93062e4b386df37d00217e"
},
{
"name":"StellaSwap: Interlay Rewarder V1",
"chain":"moonbeam",
"contract":"0x3a7572220afaddc31a72a520642111776d92b2d2"
},
{
"name":"StellaSwap: Router V1",
"chain":"moonbeam",
"contract":"0xd0a01ec574d1fc6652edf79cb2f880fd47d34ab1"
},
{
"name":"StellaSwap: xStella - GLMR Rewarder 2nd V1",
"chain":"moonbeam",
"contract":"0xb4dba7fe6fcc613963d64204fcf789e9e376679a"
},
{
"name":"StellaSwap: GLMR Rewarder First V1",
"chain":"moonbeam",
"contract":"0x69f9d134991e141c4244f397514ba05d67861cc0"
},
{
"name":"StellaSwap: CELER Rewarder 0 V1",
"chain":"moonbeam",
"contract":"0xbebd88782a1145b71df3f4986ef7686154ce01d9"
},
{
"name":"StellaSwap: MATICILO V1",
"chain":"moonbeam",
"contract":"0xfffa340944ff32f50c7935e2b5d22a7c3393b313"
},
{
"name":"StellaSwap: ETHmad - GLMR V1",
"chain":"moonbeam",
"contract":"0x9fe074a56ffa7f4079c6190be6e8452911b7e349"
},
{
"name":"StellaSwap: STELLA Token",
"chain":"moonbeam",
"contract":"0x0e358838ce72d5e61e0018a2ffac4bec5f4c88d2"
},
{
"name":"StellaSwap: SFL - 4pool Wormhole V1",
"chain":"moonbeam",
"contract":"0xb1bc9f56103175193519ae1540a0a4572b1566f6"
},
{
"name":"StellaSwap: BICO Trusted Forwarder V1",
"chain":"moonbeam",
"contract":"0x3d08ce1f9609bb02f47192ff620634d9eb0e7b56"
},
{
"name":"StellaSwap: Gass Refund V1",
"chain":"moonbeam",
"contract":"0xee42d4861b56b32776e6fe9a2fe122af0e3f4a33"
},
{
"name":"StellaSwap: xcDOT - GLMR V1",
"chain":"moonbeam",
"contract":"0xe76215efea540ea87a2e1a4bf63b1af6942481f3"
},
{
"name":"StellaSwap: 4pool LP V1",
"chain":"moonbeam",
"contract":"0xda782836b65edc4e6811c7702c5e21786203ba9d"
},
{
"name":"StellaSwap: SFL LP V1",
"chain":"moonbeam",
"contract":"0xa0aa99f71033378864ed6e499eb03612264e319a"
},
{
"name":"StellaSwap: SFL - 4pool V1",
"chain":"moonbeam",
"contract":"0x422b5b7a15fb12c518aa29f9def640b4773427f8"
},
{
"name":"StellaSwap: Acala - GLMR Rewarder V1",
"chain":"moonbeam",
"contract":"0x9de8171bebfa577d6663b594c60841fe096eff97"
},
{
"name":"StellaSwap: Zap V1",
"chain":"moonbeam",
"contract":"0x01834cf26717f0351d9762cc9cca7dc059d140df"
},
{
"name":"StellaSwap: GLMR Rewarder for UST - GLMR V1",
"chain":"moonbeam",
"contract":"0xc85ddcff71200f9673137e2f93ce504bdbf7db4e"
},
{
"name":"StellaSwap: xStella Token",
"chain":"moonbeam",
"contract":"0x06a3b410b681c82417a906993acefb91bab6a080"
},
{
"name":"StellaSwap: ETHmad - GLMR V2",
"chain":"moonbeam",
"contract":"0xa6ec79c97e533e7bddb00898e22c6908742e039b"
},
{
"name":"StellaSwap: WBTC - USDT Contract V1",
"chain":"moonbeam",
"contract":"0xcae51da6dceacd84f79df4b88d9f92035d1479e9"
},
{
"name":"StellaSwap: AVAXILO V1",
"chain":"moonbeam",
"contract":"0x96bef4719ae7c053113292e6aa7fc36e62b243e8"
},
{
"name":"StellaSwap: Swap For Gas V1",
"chain":"moonbeam",
"contract":"0xb64dee2d182fed3dd6c273303fb08f11808c9c23"
},
{
"name":"StellaSwap: Farming Centre V1",
"chain":"moonbeam",
"contract":"0x0d4f8a55a5b2583189468ca3b0a32d972f90e6e5"
},
{
"name":"StellaSwap: FTMILO V1",
"chain":"moonbeam",
"contract":"0x096352f7ea415a336b41fc48b33142eff19a8ad8"
},
{
"name":"StellaSwap: Acala Rewarder V1",
"chain":"moonbeam",
"contract":"0xb7b5d3659ad213478bc8bfb94d064d0efdda8f7c"
},
{
"name":"StellaSwap: USDC Rewarder V1",
"chain":"moonbeam",
"contract":"0xa52123adc0bc5c4c030d1ff4f5dad966366a646c"
},
{
"name":"StellaSwap: Vault V1",
"chain":"moonbeam",
"contract":"0x54e2d14df9348b3fba7e372328595b9f3ae243fe"
},
{
"name":"StellaSwap: CELER Rewarder 1 V1",
"chain":"moonbeam",
"contract":"0x70cbd76ed57393e0cd81e796de850080c775d24f"
},
{
"name":"StellaSwap: Stella Timelock V1",
"chain":"moonbeam",
"contract":"0xc6f73b028cd3154a5bb87f49aa43aa259a6522fb"
},
{
"name":"StellaSwap: GLMR - MAI Vault V1",
"chain":"moonbeam",
"contract":"0x3a82f4da24f93a32dc3c2a28cfa9d6e63ec28531"
},
{
"name":"StellaSwap: UST - GLMR V1",
"chain":"moonbeam",
"contract":"0x556d9c067e7a0534564d55f394be0064993d2d3c"
},
{
"name":"StellaSwap: SFL - axlUSDC - 4pool V1",
"chain":"moonbeam",
"contract":"0xa1ffdc79f998e7fa91ba3a6f098b84c9275b0483"
},
{
"name":"StellaSwap: Stable Router V1",
"chain":"moonbeam",
"contract":"0xb0dfd6f3fddb219e60fcdc1ea3d04b22f2ffa9cc"
},
{
"name":"StellaSwap: ATOM - GLMR Rewarder New V1",
"chain":"moonbeam",
"contract":"0x5aa224966e302424ec13a4f51b80bcfc205984b6"
},
{
"name":"StellaSwap: CELR Rewarder V1",
"chain":"moonbeam",
"contract":"0x05ad30253f0b20be35d84253d6aca8bd7ec0c66c"
},
{
"name":"StellaSwap: Router V3",
"chain":"moonbeam",
"contract":"0xe6d0ed3759709b743707dcfecae39bc180c981fe"
},
{
"name":"StellaSwap: xStella - GLMR Rewarder V1",
"chain":"moonbeam",
"contract":"0x896135ff51debe8083a2e03f9d44b1d3c77a0324"
},
{
"name":"StellaSwap: XStella - MAI Vault V1",
"chain":"moonbeam",
"contract":"0x3756465c5b1c1c4cee473880c9726e20875284f1"
},
{
"name":"StellaSwap: ATOM - USDC Rewarder New V1",
"chain":"moonbeam",
"contract":"0x5546e272c67fac10719f1223b1c0212fa3e41a8f"
},
{
"name":"StellaSwap: SFL - athUSDC - 4pool V1",
"chain":"moonbeam",
"contract":"0x715d7721fa7e8616ae9d274704af77857779f6f0"
},
{
"name":"StellaSwap: IDO Locker V1",
"chain":"moonbeam",
"contract":"0x4b1381b5b959a8ba7f44414c7d758e53d500a8a9"
},
{
"name":"StellaSwap: Locker V1",
"chain":"moonbeam",
"contract":"0x8995066b7f1fb3abe3c88040b677d03d607a0b58"
},
{
"name":"StellaSwap: ATOM - USDC - GLMR Rewarder V1",
"chain":"moonbeam",
"contract":"0xe06e720aaed5f5b817cb3743108ae0a12fe69e9b"
},
{
"name":"StellaSwap: Mistake in Rewarder V1",
"chain":"moonbeam",
"contract":"0x168ceb7e49c21e3f37820a34590171214a765f5f"
},
{
"name":"StellaSwap: LP 4pool - Wormhole V1",
"chain":"moonbeam",
"contract":"0xb326b5189aa42acaa3c649b120f084ed8f4dcaa6"
},
{
"name":"StellaSwap: Farms V1",
"chain":"moonbeam",
"contract":"0xedfb330f5fa216c9d2039b99c8ce9da85ea91c1e"
},
{
"name":"StellaSwap: Factory V1",
"chain":"moonbeam",
"contract":"0x68a384d826d3678f78bb9fb1533c7e9577dacc0e"
},
{
"name":"StellaSwap: anyETH-madETH Pool",
"chain":"moonbeam",
"contract":"0xb86271571c90ad4e0c9776228437340b42623402"
},
{
"name":"StellaSwap: Dual Farms V2",
"chain":"moonbeam",
"contract":"0xf3a5454496e26ac57da879bf3285fa85debf0388"
},
{
"name":"StellaSwap: CELER Rewarder 01 - 02 V1",
"chain":"moonbeam",
"contract":"0x713f76076283fcd81babe06c76ff51485edf9d5e"
},
{
"name":"StellaSwap: SCNFT Token",
"chain":"moonbeam",
"contract":"0x5f23a6a0b6b90fdeeb4816afbfb2ec0408fda59e"
},
{
"name":"StellaSwap: ATOM - GLMR - GLMR Rewarder V1",
"chain":"moonbeam",
"contract":"0xe60c41de5537418fde05b804df077397dfa84d75"
},
{
"name":"StellaSwap: Timelock Main V1",
"chain":"moonbeam",
"contract":"0x9a8693c6f7bf0f44e885118f3f83e2cdb4e611b8"
},
{
"name":"StellaSwap: MAI - B4P - Wormhole V1",
"chain":"moonbeam",
"contract":"0xf0a2ae65342f143fc09c83e5f19b706abb37414d"
},
{
"name":"StellaSwap: LP Token V1",
"chain":"moonbeam",
"contract":"0x7b17122b941d2173192c7d8d68faabdc88421326"
},
{
"name":"StellaSwap: Multisig V1",
"chain":"moonbeam",
"contract":"0x4300e09284e3bb4d9044ddab31efaf5f3301daba"
},
{
"name":"StellaSwap: Router V2",
"chain":"moonbeam",
"contract":"0x70085a09d30d6f8c4ecf6ee10120d1847383bb57"
},
{
"name":"StellaSwap: DOTxc - GLMR V1",
"chain":"moonbeam",
"contract":"0x505b0a5458dd12605b84bb2928dd2bc5b44993b9"
},
{
"name":"StellaSwap: SFL - MAI - 4pool V1",
"chain":"moonbeam",
"contract":"0x7fbe3126c03444d43fc403626ec81e3e809e6b46"
},
{
"name":"StellaSwap: xStella - USDC Rewarder V1",
"chain":"moonbeam",
"contract":"0xfa16d5b8bf03677945f0a750c8d2a30001b2fa93"
},
{
"name":"StellaSwap: madUSDC - GLMR V1",
"chain":"moonbeam",
"contract":"0x9200cb047a9c4b34a17ccf86334e3f434f948301"
}
],
"slug":"stellaswap",
"createdAt":1699292612617,
"tvlChange1d":{
"moonbeam":-0.748278690902012
},
"logo":{
"small":{
"width":36,
"fileName":"stellaswap-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":510,
"fileName":"stellaswap-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":510
},
"full":{
"width":3000,
"fileName":"stellaswap-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"chains":[
"moonbeam"
],
"usersChange7d":{
"moonbeam":-17.2727272727273
},
"marketData":{
"symbol":"stella",
"marketCap":808908,
"marketCapRank":2865,
"priceChangePercentage1y":-43.01356,
"currentPrice":0.01729378,
"priceChangePercentage14d":-17.23772,
"contracts":{
"moonbeam":"0x0e358838ce72d5e61e0018a2ffac4bec5f4c88d2"
},
"priceChangePercentage60d":-39.75633,
"priceChangePercentage30d":-26.13934,
"priceChangePercentage24h":-4.63782,
"priceChangePercentage200d":-74.57003,
"marketCapChangePercentage24h":-4.62971,
"priceChange24h":-0.0008410608839097,
"marketCapChange24h":-39268.122562502,
"priceChangePercentage7d":-7.91278
},
"projectCreationDate":1644828523000,
"contracts":[
{
"chain":"moonbeam",
"contract":"0x0e358838ce72d5e61e0018a2ffac4bec5f4c88d2"
}
],
"updatedAt":1722544694830,
"category":"dex",
"description":"StellaSwap is one of the first automated market-making (AMM), decentralized exchange (DEX) for the Moonbeam parachain network. The unique value proposition of StellaSwap is that we're committed in establishing a strong foundation with our native token, STELLA, as a governance token, diverse farms, a built in bridge and user-centered service. \r\n\r\nStellaSwap's main objective is to create a broader range of network effects to address the issues of liquidity in the DeFi space, instead of limiting ourselves to a single solution like many DEXs are doing now. This manifests itself in the diverse product suite of StellaSwap that will be explained in more details. Our products are structured in such a way that facilitates decentralized governance of STELLA holders, while continuing to innovate on the collective foundations by design.",
"usersChange1d":{
"moonbeam":-6.18556701030928
}
}
}
```
### Query a Category {: #query-a-category}
You can also query the API by [category](#category-and-tags). For example, you can retrieve information about all NFT projects with the following query:
```bash
https://apps.moonbeam.network/api/ds/v1/app-dir/projects?category=nfts
```
??? code "API Response to Querying NFT projects"
```json
{
"projects":[
{
"urls":{
"telegram":"https://t.me/nfts2me",
"website":"https://nfts2me.com/",
"try":"https://nfts2me.com/",
"twitter":"https://twitter.com/nfts2me",
"medium":"https://nfts2me.medium.com/",
"discord":"https://nfts2me.com/discord/"
},
"slug":"nfts2me",
"createdAt":1699292617117,
"logo":{
"small":{
"width":36,
"fileName":"nfts2me-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":512,
"fileName":"nfts2me-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":512
},
"full":{
"width":3000,
"fileName":"nfts2me-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"NFTs2Me",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1673608509000,
"shortDescription":"NFTs2Me is a toolkit for creating and managing NFT projects.",
"contracts":[
{
"chain":"moonbeam",
"contract":"0x2269bCeB3f4e0AA53D2FC43B1B7C5C5D13B119a5"
}
],
"updatedAt":1722498896566,
"category":"nfts",
"description":"NFTs2Me is a tool for creating and managing NFT projects. It includes features such as an art generator, delayed reveal, minting widget, token gating, and support for multiple blockchain platforms. It also offers customization options, an affiliate system, automatic logo and banner generation, and support for redeemable NFTs. It is user-friendly and suitable for those new to the world of NFTs.\n\nIn addition to these features, NFTs2Me also offers a minting widget and free IPFS hosting to make it simple to mint and store your NFTs securely and efficiently. The minting widget allows you to easily create and mint new NFTs, while the free IPFS hosting provides a secure and decentralized way to store your NFTs.",
"id":"nfts2me",
"tags":[
"NFT",
"Tool"
]
},
{
"urls":{
"telegram":"https://t.me/rmrkapp",
"website":"https://singular.app/",
"try":"https://singular.app/",
"twitter":"https://twitter.com/RmrkSingular",
"discord":"https://discord.gg/TjB6v5AGZz"
},
"slug":"singular-app",
"createdAt":1699292616171,
"logo":{
"small":{
"width":36,
"fileName":"singular-app-logo-small.png",
"mimeType":"image/png",
"height":36
},
"large":{
"width":400,
"fileName":"singular-app-logo-large.png",
"mimeType":"image/png",
"height":400
},
"full":{
"width":3000,
"fileName":"singular-app-logo-full.png",
"mimeType":"image/png",
"height":3000
}
},
"name":"Singular App",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1686240710000,
"shortDescription":"The home of NFTs by @RmrkApp. Create and trade your nestable, equippable, soulbound, and multi-asset NFTs with us - no coding required.",
"contracts":[
],
"updatedAt":1722498914806,
"category":"nfts",
"description":"Singular is an NFT 2.0 marketplace that allows users to buy, sell, and trade both regular and advanced NFTs. Users can create and/or connect a wallet, browse digital items, and securely conduct transactions using blockchain technology.",
"id":"singular-app",
"tags":[
"NFT Marketplaces"
]
},
{
"urls":{
"telegram":"https:/t.me/metacourtgg",
"website":"https://www.metacourt.gg/",
"try":"https://www.metacourt.gg/",
"twitter":"https://twitter.com/metacourtgg",
"medium":"https://metacourtgg.medium.com/",
"discord":"https://discord.gg/9AnnfKCb39"
},
"slug":"metacourt",
"createdAt":1699292616238,
"logo":{
"small":{
"width":36,
"fileName":"metacourt-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":512,
"fileName":"metacourt-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":512
},
"full":{
"width":3000,
"fileName":"metacourt-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"Metacourt",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1663756794000,
"shortDescription":"Metacourt created NFTdeals for anyone who wants to become an influencer and trade their social media",
"contracts":[
],
"updatedAt":1722498888422,
"category":"nfts",
"description":"Influencer accelerator for anyone who wants to become an influencer in the space. We allow selling your social media through NFTs and joining influencer marketing campaigns.",
"id":"metacourt",
"tags":[
"NFT Marketplaces"
]
},
{
"urls":{
"telegram":"https://t.me/tofuNFT",
"website":"https://tofunft.com/",
"try":"https://tofunft.com/",
"twitter":"https://twitter.com/tofuNFT",
"medium":"https://medium.com/tofunftofficial",
"discord":"https://discord.com/invite/3wFUTZmTm7"
},
"slug":"tofunft",
"createdAt":1699292615874,
"logo":{
"small":{
"width":36,
"fileName":"tofunft-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":400,
"fileName":"tofunft-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":400
},
"full":{
"width":3000,
"fileName":"tofunft-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"tofuNFT",
"chains":[
"moonbeam",
"moonriver"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1644828523000,
"shortDescription":"The largest multichain NFT marketplace",
"contracts":[
],
"updatedAt":1722498924881,
"category":"nfts",
"description":"tofuNFT.com is an NFT marketplace focused on GameFi and collectibles, rebranded from SCV’s NFT market. Enjoy exploring & trading with your buddies!",
"id":"tofunft",
"tags":[
"NFT Marketplaces",
"NFT"
]
},
{
"urls":{
"website":"https://d-book.io",
"try":"https://d-book.io",
"twitter":"https://twitter.com/dbook_io"
},
"slug":"d-book.io",
"createdAt":1699292617021,
"logo":{
"small":{
"width":129,
"fileName":"d-book.io-logo-small.png",
"mimeType":"image/png",
"height":36
},
"large":{
"width":129,
"fileName":"d-book.io-logo-large.png",
"mimeType":"image/png",
"height":36
},
"full":{
"width":3000,
"fileName":"d-book.io-logo-full.png",
"mimeType":"image/png",
"height":3000
}
},
"name":"D-book.io",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1682016612000,
"shortDescription":"Buğra Ayan is a speaker,and university lecturer in Turkey who founded the Web3 Association Turkey.",
"contracts":[
{
"chain":"moonbeam",
"contract":"0x8d4BA02D0973749ad7c646DcaAa60BDC66F6F6D2"
}
],
"updatedAt":1722498866417,
"category":"nfts",
"description":"We are an NFT Book Platform that connects authors and the decentralized world, aiming for a transformation ecosystem.",
"id":"d-book.io",
"tags":[
"NFT Marketplaces",
"NFT"
]
},
{
"urls":{
"telegram":"https://t.me/BcmHuntGroup",
"website":"https://bcmhunt.com/",
"try":"https://bcmhunt.com/",
"twitter":"https://twitter.com/bcmhunt",
"medium":"https://medium.com/bcmhunt",
"discord":"https://discord.com/invite/Ee9aJ287J2"
},
"slug":"blockchain-monster-hunt",
"createdAt":1699292616780,
"logo":{
"small":{
"width":36,
"fileName":"blockchain-monster-hunt-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":510,
"fileName":"blockchain-monster-hunt-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":510
},
"full":{
"width":3000,
"fileName":"blockchain-monster-hunt-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"Blockchain Monster Hunt",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1644828523000,
"shortDescription":"The First Multichain NFT Monster Hunt",
"contracts":[
],
"updatedAt":1722498855937,
"category":"nfts",
"description":"Blockchain Monster Hunt (BCMH) is the world’s first multi-chain game that runs entirely on the blockchain itself. Inspired by Pokémon-GO,BCMH allows players to continuously explore brand new places on the blockchain to hunt and battle monsters. Each block on the blockchain is a unique digital space where a limited number of monsters (of the same DNA gene and rarity) may exist. Players and collectors can hunt or battle for a chance to capture these unique monsters and to earn coins.",
"id":"blockchain-monster-hunt",
"tags":[
"NFT",
"Gaming",
"GLMR Grants"
]
},
{
"urls":{
"website":"https://speedboat.studio/",
"try":"https://speedboat.studio/",
"twitter":"https://twitter.com/Speedboat_STDO",
"medium":"https://medium.com/@speedboat_studio",
"discord":"https://discord.gg/y7TQbtEWSV"
},
"slug":"speedboat.studio",
"createdAt":1699292616328,
"logo":{
"small":{
"width":36,
"fileName":"speedboat.studio-logo-small.png",
"mimeType":"image/png",
"height":36
},
"large":{
"width":190,
"fileName":"speedboat.studio-logo-large.png",
"mimeType":"image/png",
"height":190
},
"full":{
"width":3000,
"fileName":"speedboat.studio-logo-full.png",
"mimeType":"image/png",
"height":3000
}
},
"name":"Speedboat",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1657584952000,
"shortDescription":"Your no-code Web3 toolkit",
"contracts":[
],
"updatedAt":1722498916466,
"category":"nfts",
"description":"Speedboat is a Web3 toolkit for everyone. Built on the idea that NFTs are not just expensive JPEGs, but programmable experiences.",
"id":"speedboat.studio",
"tags":[
"NFT",
"Tool"
]
},
{
"urls":{
"telegram":"https://t.me/+qGh0InPSPc1iMTNk",
"website":"https://www.glmrapes.com/",
"try":"https://www.glmrapes.com/",
"twitter":"https://twitter.com/GLMRApes",
"discord":"https://discord.com/invite/glmrapes"
},
"web3goContracts":[
{
"name":"GLMR Apes: GLMR Ape",
"chain":"moonbeam",
"contract":"0x8fbe243d898e7c88a6724bb9eb13d746614d23d6"
},
{
"name":"GLMR Apes: GLMR Jungle",
"chain":"moonbeam",
"contract":"0xcb13945ca8104f813992e4315f8ffefe64ac49ca"
}
],
"currentTx":{
"moonbeam":7830
},
"slug":"glmr-apes",
"web3goIDs":[
"GLMR Apes"
],
"createdAt":1699292616827,
"logo":{
"small":{
"width":47,
"fileName":"glmr-apes-logo-small.png",
"mimeType":"image/png",
"height":36
},
"large":{
"width":528,
"fileName":"glmr-apes-logo-large.png",
"mimeType":"image/png",
"height":408
},
"full":{
"width":3000,
"fileName":"glmr-apes-logo-full.png",
"mimeType":"image/png",
"height":3000
}
},
"name":"GLMR APES",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"usersChange7d":{
"moonbeam":-66.6666666666667
},
"currentUsers":{
"moonbeam":1531
},
"projectCreationDate":1644828523000,
"shortDescription":"The first NFT collection on GLMR by & for the community",
"contracts":[
],
"updatedAt":1722547408370,
"category":"nfts",
"description":"GLIMMER APES is the first NFT collection on GLMR by & for the community. The longer you’re bonding with GLMR Apes and the friendlier their behavior. Join the troops as soon as possible to become an EARLY APE, take part in our giveaways and games and land in the GLMR APE VIP CLUB.",
"id":"glmr-apes",
"tags":[
"NFT",
"Gaming"
],
"usersChange1d":{
"moonbeam":0
}
},
{
"urls":{
"website":"https://snakesoldiers.com",
"try":"https://snakesoldiers.com",
"twitter":"https://twitter.com/snakesoldiers",
"github":"https://github.com/steven2308/snake-soldiers-contracts",
"medium":"https://medium.com/@snakesoldiers/emoting-to-influence-the-hatch-df3eab7e45b8",
"discord":"http://discord.gg/A6zQSz4YU4"
},
"slug":"snake-soldiers",
"createdAt":1699292616971,
"logo":{
"small":{
"width":36,
"fileName":"snake-soldiers-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":400,
"fileName":"snake-soldiers-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":400
},
"full":{
"width":3000,
"fileName":"snake-soldiers-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"Snake Soldiers",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1691439275000,
"shortDescription":"NFT game collection divided in 3 categories: Generals, Commanders and Soldiers🐍. Built on Moonbeam",
"contracts":[
{
"chain":"moonbeam",
"contract":"0x3ab955216BdD76f51fbe02A3fe237D6612BBD09F"
}
],
"updatedAt":1722498915320,
"category":"nfts",
"description":"Snake Soldiers is an NFT collection with a supply of at most 5k units, all unique and distributed among 3 ranks. Each snake will be usable inside a play to own game, where snakes will be the main characters, necessary to interact with the SerpenTerra ecosystem. This metaverse will be based on the RMRK 2.0 standard, making forward compatible and giving super powers to the NFTs.",
"id":"snake-soldiers",
"tags":[
"NFT"
]
},
{
"urls":{
"telegram":"https://t.me/+LqmDOeGUQdRmYjVh%60%60",
"website":"https://omni-x.io",
"try":"https://omni-x.io",
"twitter":"https://twitter.com/omnix_nft",
"github":"https://github.com/Omni-X-NFT",
"discord":"https://discord.gg/omni-x"
},
"slug":"omni-x",
"createdAt":1699292617077,
"logo":{
"small":{
"width":36,
"fileName":"omni-x-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":107,
"fileName":"omni-x-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":108
},
"full":{
"width":3000,
"fileName":"omni-x-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"Omni-X",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1673811786000,
"shortDescription":"The first natively omnichain NFT platform",
"contracts":[
],
"updatedAt":1722498898538,
"category":"nfts",
"description":"Omni X is an omnichain NFT protocol and marketplace that connects communities, creators, and enthusiasts across multiple blockchains. \n\nWe provide tooling for creating ONFT collections, bridging regular NFTs to ONFTs and grant access to unparalleled liquidity that allows users to buy and sell NFTs from any blockchain to any other blockchain.",
"id":"omni-x",
"tags":[
"NFT Marketplaces",
"Infrastructure"
]
},
{
"urls":{
"website":"https://www.publicpressure.io/",
"try":"https://www.publicpressure.io/",
"twitter":"https://twitter.com/jointhepressure",
"discord":"https://discord.gg/publicpressure"
},
"slug":"publicpressure",
"createdAt":1702283744356,
"logo":{
"small":{
"width":36,
"fileName":"publicpressure-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":400,
"fileName":"publicpressure-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":400
},
"full":{
"width":3000,
"fileName":"publicpressure-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"Public Pressure",
"chains":[
"moonriver"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1651597275000,
"shortDescription":"Support your favorite artists, own their music, get rewarded.",
"contracts":[
],
"updatedAt":1722498907699,
"category":"nfts",
"description":"We are the web3 music platform powered by artists, labels and fans",
"id":"publicpressure",
"tags":[
"NFT Marketplaces"
]
},
{
"currentTx":{
"moonbeam":8409
},
"web3goIDs":[
"Moonbeans"
],
"name":"Moonbeans",
"currentUsers":{
"moonbeam":1134
},
"coinGeckoId":"moonbeans",
"shortDescription":"Galactic Co-Op & Profit sharing NFT platform and soon to be Metaverse",
"id":"moonbeans",
"tags":[
"NFT Marketplaces"
],
"urls":{
"website":"https://moonbeans.io/",
"twitter":"https://twitter.com/moonbeansio",
"github":"https://github.com/m00nbeans",
"discord":"https://discord.com/invite/qqE9aBPzQ9",
"telegram":"https://t.me/moonbeansio",
"try":"https://moonbeans.io/",
"medium":"https://medium.com/@MoonBeans"
},
"web3goContracts":[
{
"name":"Moonbeans: Beanie Distributor V2",
"chain":"moonbeam",
"contract":"0xda6367c6510d8f2d20a345888f9dff3eb3226b02"
},
{
"name":"Moonbeans: Marketplace V9",
"chain":"moonbeam",
"contract":"0x683724817a7d526d6256aec0d6f8ddf541b924de"
},
{
"name":"Moonbeans: Storefront Ownership V1",
"chain":"moonbeam",
"contract":"0x971dfedd548f2269e515957404cbbee1f507cd01"
}
],
"slug":"moonbeans",
"createdAt":1699292615978,
"logo":{
"small":{
"width":36,
"fileName":"moonbeans-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":400,
"fileName":"moonbeans-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":400
},
"full":{
"width":3000,
"fileName":"moonbeans-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"chains":[
"moonbeam",
"moonriver"
],
"defiLLamaTvlExist":false,
"usersChange7d":{
"moonbeam":0
},
"marketData":{
"symbol":"beans",
"marketCap":0,
"priceChangePercentage1y":-62.22489,
"currentPrice":0.062264,
"priceChangePercentage14d":-13.93552,
"contracts":{
},
"priceChangePercentage60d":-44.93764,
"priceChangePercentage30d":-33.587,
"priceChangePercentage24h":-0.05451,
"priceChangePercentage200d":-83.0363,
"marketCapChangePercentage24h":0,
"priceChange24h":-0.0000339560550113,
"marketCapChange24h":0,
"priceChangePercentage7d":-5.36696
},
"projectCreationDate":1644828523000,
"contracts":[
{
"chain":"moonbeam",
"contract":"0x65b09ef8c5a096c5fd3a80f1f7369e56eb932412"
},
{
"chain":"moonriver",
"contract":"0xC2392DD3e3fED2c8Ed9f7f0bDf6026fcd1348453"
}
],
"updatedAt":1722548296818,
"category":"nfts",
"description":"Moonbeans is a fully functional NFT marketplace launched on October 8th 2021, after releasing 465 Beanies into the Moonriver network to wreak havoc. The platform is still in beta, but has been performing incredibly well. With minimal fees for artists, traders, and project developers, Moonbeans aims to grow and aid the Moonrver network as a whole to develop, learn, and earn. With multiple collections now live (Beanies, Damned Pirates Society), minting (RivrMaids), Moonbeans is the heart of the Moonriver NFT ecosystem.",
"usersChange1d":{
"moonbeam":0
}
},
{
"urls":{
"telegram":"https://t.me/blocsport",
"website":"https://blocsport.one/",
"try":"https://blocsport.one/",
"twitter":"https://twitter.com/blocsport1",
"medium":"https://blocsport1.medium.com/"
},
"slug":"blocsport-one",
"createdAt":1699292616637,
"logo":{
"small":{
"width":36,
"fileName":"blocsport-one-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":400,
"fileName":"blocsport-one-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":400
},
"full":{
"width":3000,
"fileName":"blocsport-one-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"Blocsport.one",
"chains":[
"moonriver"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1644828523000,
"shortDescription":"Web 3.0 metaverse, smart sports money, athlete NFT launchpad & assets tokenization",
"contracts":[
],
"updatedAt":1722498857332,
"category":"nfts",
"description":"Blocsport.one is a Swiss sports tech company founded in 2019 that is transforming the sports business by building a transparent and reliable sports ecosystem uniting athletes, clubs, and fans based on blockchain. Company owns NFTdeals.io exclusive marketplace and has the biometric-enabled football scouting DApp live. Blocsport.one helps the young promising athletes get the money and exposure for their career development, which is nobody else doing in the world.",
"id":"blocsport-one",
"tags":[
"NFT"
]
},
{
"urls":{
"telegram":"https://t.me/mintverse",
"website":"https://www.mintverse.com/",
"try":"https://www.mintverse.com/",
"twitter":"https://twitter.com/mintverse_",
"medium":"https://medium.com/mintverse",
"discord":"https://discord.com/invite/mhhnbvAaq9"
},
"slug":"mintverse",
"createdAt":1702283733666,
"logo":{
"small":{
"width":36,
"fileName":"mintverse-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":400,
"fileName":"mintverse-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":400
},
"full":{
"width":3000,
"fileName":"mintverse-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"Mintverse",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1651597514000,
"shortDescription":"Mint, Explore & Trade Liquid NFT Assets Across Multiple Chains",
"contracts":[
],
"updatedAt":1722498889300,
"category":"nfts",
"description":"Comprehensive NFT Aggregation Marketplace with a 0% trading fee",
"id":"mintverse",
"tags":[
"NFT Marketplaces"
]
},
{
"urls":{
"telegram":"https://t.me/rmrkapp",
"website":"https://upgradooor.app",
"try":"https://upgradooor.app",
"twitter":"https://x.com/rmrkapp",
"github":"https://github.com/rmrk-team",
"medium":"https://medium.com/rmrkapp"
},
"slug":"upgradooor",
"createdAt":1699292616895,
"logo":{
"small":{
"width":36,
"fileName":"upgradooor-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":512,
"fileName":"upgradooor-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":512
},
"full":{
"width":3000,
"fileName":"upgradooor-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"Upgradooor",
"chains":[
"moonbeam",
"moonriver"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1692259742000,
"shortDescription":"Upgrade your NFT 1.0 collections to NFT 2.0 by wrapping them into advanced functionality",
"contracts":[
],
"updatedAt":1722498927244,
"category":"nfts",
"description":"As a collection issuer, use Upgradooor to initialize the process of upgrading your collection to NFT 2.0 if you are currently using ERC721.\n\nAs a holder, once the collection owner initiates the process, you can wrap any NFT you hold in that collection and instantly turn it into an equippable, multi-asset, composable NFT with no added risk.\n\nYou can always unwrap at will, and all the changes will still wait for you when you decide to re-claim the 2.0 wrapper again.\n\nUpgrading allows you to:\n\n- add more assets (outputs) to a legacy NFT, preventing needless airdrop spam\n- airdrop NFTs into the NFT itself, preventing detachment of context, and saving tremendous amounts of gas by letting people transfer just the parent NFT\n- define equippable settings and even achieve compatibility with other collections, for cross collection equippables and thus cross collection royalties and commissions\n- see your NFTs on Singular, and use GBM auctions as a unique and novel listing mechanic",
"id":"upgradooor",
"tags":[
"NFT",
"Tool"
]
},
{
"urls":{
"telegram":"https://t.me/moonfit_official_community",
"website":"https://moonfit.xyz/",
"try":"https://moonfit.xyz/",
"twitter":"https://twitter.com/MoonFitOfficial",
"discord":"https://discord.gg/hStdUVtHXp"
},
"slug":"moonfit",
"createdAt":1702283734897,
"logo":{
"small":{
"width":36,
"fileName":"moonfit-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":400,
"fileName":"moonfit-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":400
},
"full":{
"width":3000,
"fileName":"moonfit-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"MoonFit",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1654692249000,
"shortDescription":"Web3 & NFT Lifestyle App That Pays You Anytime You Burn Calories",
"contracts":[
],
"updatedAt":1722498891201,
"category":"nfts",
"description":"MoonFit is a Web3 Lifestyle App that promotes active living by rewarding users with tokens and NFTs anytime they burn calories through physical activities.",
"id":"moonfit",
"tags":[
"NFT",
"Gaming"
]
},
{
"urls":{
"telegram":"https://t.me/rmrkapp",
"website":"https://rmrk.app/",
"try":"https://rmrk.app/",
"twitter":"https://twitter.com/rmrkapp",
"discord":"https://discord.com/invite/bV9kQbVC99"
},
"slug":"rmrk",
"createdAt":1699292615938,
"logo":{
"small":{
"width":36,
"fileName":"rmrk-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":400,
"fileName":"rmrk-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":400
},
"full":{
"width":3000,
"fileName":"rmrk-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"RMRK",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"marketData":{
"symbol":"rmrk",
"marketCap":5985029,
"marketCapRank":1602,
"priceChangePercentage1y":-64.99216,
"currentPrice":0.62974,
"priceChangePercentage14d":-24.26661,
"contracts":{
"moonbeam":"0x524d524b4c9366be706d3a90dcf70076ca037ae3"
},
"priceChangePercentage60d":-51.72181,
"priceChangePercentage30d":-30.11256,
"priceChangePercentage24h":-2.58554,
"priceChangePercentage200d":-75.55551,
"marketCapChangePercentage24h":-2.50147,
"priceChange24h":-0.01671434617594,
"marketCapChange24h":-153554.8536219,
"priceChangePercentage7d":-1.5052
},
"coinGeckoId":"rmrk",
"projectCreationDate":1644828523000,
"shortDescription":"Creators of NFTs 2.0 via ERC6059, ERC6220, ERC5773, EIP6381, and EIP6454.\nNFT equippables, future compatibility, reputation, and token balances.",
"contracts":[
],
"updatedAt":1722548302467,
"category":"nfts",
"description":"With the RMRK NFT Building Block System\nOur ERC NFT standards allow you to unlock the true potential of NFTs.\nTailored to work with each other, these EVM smart contracts will help you create your NFT projects of varying complexity.",
"id":"rmrk",
"tags":[
"NFT",
"Infrastructure"
]
},
{
"urls":{
"website":"https://www.mynft.com/",
"try":"https://bridge.mynft.com/home",
"twitter":"https://twitter.com/mynft"
},
"slug":"mynft",
"createdAt":1699292616578,
"logo":{
"small":{
"width":36,
"fileName":"mynft-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":400,
"fileName":"mynft-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":400
},
"full":{
"width":3000,
"fileName":"mynft-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"myNFT",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1644828523000,
"shortDescription":"The marketplace that puts the power back in your hands",
"contracts":[
],
"updatedAt":1722498895020,
"category":"nfts",
"description":"myNFT is the marketplace that puts the power back in your hands. It is a creative workshop, a trading platform and a discovery engine, helping you tell your story and share your passions, on your own terms. myNFT is built on decentralized technologies empowering you to create, trade, and discover. myNFT is built by Perpetual Altruism, a leader in the NFT space and the creator of charitable NFT publisher Cryptograph and the GBM auction system. Perpetual Altruism is backed by prominent investors and creators and is also the recipient of grants from the Web3 Foundation and the Moonbeam network for their work on the decentralized internet, which powers myNFT.",
"id":"mynft",
"tags":[
"NFT Marketplaces",
"GLMR Grants",
"MOVR Grants"
]
},
{
"urls":{
"website":"https://readl.co/",
"try":"https://readl.co/",
"twitter":"https://twitter.com/readl_co",
"medium":"https://medium.com/@readlnetwork",
"discord":"https://discord.gg/XPTENepHqY"
},
"slug":"readl",
"createdAt":1702283745749,
"logo":{
"small":{
"width":36,
"fileName":"readl-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":512,
"fileName":"readl-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":512
},
"full":{
"width":3000,
"fileName":"readl-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"Readl",
"chains":[
"moonriver"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1655885161000,
"shortDescription":"Bringing the publishing industry to web3",
"contracts":[
],
"updatedAt":1722498910044,
"category":"nfts",
"description":"Readl is the protocol that provides publishers and storytellers with the infrastructure to publish their content on the blockchain, while providing a user-friendly platform to enjoy any story, in any format.",
"id":"readl",
"tags":[
"NFT Marketplaces",
"MOVR Grants"
]
},
{
"urls":{
"telegram":"https://t.me/rmrkapp",
"website":"https://emotes.app",
"try":"https://emotes.app",
"twitter":"https://x.com/rmrkapp",
"github":"https://github.com/rmrk-team",
"medium":"https://medium.com/rmrkapp"
},
"slug":"emotes.app",
"createdAt":1699292616951,
"logo":{
"small":{
"width":36,
"fileName":"emotes.app-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":512,
"fileName":"emotes.app-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":512
},
"full":{
"width":3000,
"fileName":"emotes.app-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"Emotes.app",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1692254489000,
"shortDescription":"React on anyone's NFT - throw 💩 at those apes, give a 🤗 to those Pudgies!",
"contracts":[
],
"updatedAt":1722498871347,
"category":"nfts",
"description":"Emotes.app is a RMRK mini-app which allows you to send emotes / reactions to anyone's NFT. It utilizes RMRK's ERC7009 and is trivial to integrate into any project wanting to take advantage of the community's reactions to their NFTs.\n\nUse it to direct storylines, affect NFT egg hatching, or just do relative price comparison when influencers like one NFTs and dislike another!",
"id":"emotes.app",
"tags":[
"NFT",
"Social"
]
},
{
"urls":{
"telegram":"https://twitter.com/PolkaPets",
"website":"https://www.polkapet.world/",
"try":"https://www.polkapet.world/",
"twitter":"https://twitter.com/PolkaPets",
"medium":"https://polkapetworld.medium.com/"
},
"slug":"polkapet-world",
"createdAt":1702283743596,
"logo":{
"small":{
"width":36,
"fileName":"polkapet-world-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":400,
"fileName":"polkapet-world-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":400
},
"full":{
"width":3000,
"fileName":"polkapet-world-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"PolkaPets",
"chains":[
"moonriver"
],
"defiLLamaTvlExist":false,
"marketData":{
"priceChangePercentage60d":1206.42918,
"symbol":"pets",
"marketCap":0,
"priceChangePercentage30d":619.39533,
"priceChangePercentage200d":135.91624,
"priceChangePercentage1y":355.00061,
"currentPrice":0.00515699,
"priceChangePercentage14d":-15.30948,
"contracts":{
"moonriver":"0x1e0f2a75be02c025bd84177765f89200c04337da"
},
"priceChangePercentage7d":749.62625
},
"coinGeckoId":"polkapet-world",
"projectCreationDate":1651157216000,
"shortDescription":"Welcome to PolkaPet World",
"contracts":[
],
"updatedAt":1722548303208,
"category":"nfts",
"description":"An immersive NFT collection created in partnership with the biggest and best PolkaDot projects ",
"id":"polkapet-world",
"tags":[
"NFT"
]
},
{
"urls":{
"website":"https://www.moonarines.com/",
"try":"https://www.moonarines.com/",
"discord":"https://discord.gg/bXhSyW8htW"
},
"slug":"moonarines",
"createdAt":1702283733870,
"logo":{
"small":{
"width":36,
"fileName":"moonarines-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":400,
"fileName":"moonarines-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":400
},
"full":{
"width":3000,
"fileName":"moonarines-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"Moonarines",
"chains":[
"moonriver"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1654792422000,
"shortDescription":"Be part of the conquest of the digital space",
"contracts":[
],
"updatedAt":1722498889804,
"category":"nfts",
"description":"The Moonarines are unique NFT characters starting soon on the Moonriver Network!\nWith the Moonarines, the NFT owners will be taken to an unforgettable adventure to explore the Cryptoverse!",
"id":"moonarines",
"tags":[
"NFT"
]
},
{
"urls":{
"telegram":"https://t.me/NFTrade",
"website":"https://nftrade.com/",
"try":"https://nftrade.com/",
"twitter":"https://twitter.com/NFTradeOfficial",
"medium":"https://medium.com/@NFTrade",
"discord":"https://discord.com/invite/SESqfsyw8k"
},
"slug":"nftrade",
"createdAt":1699292616005,
"logo":{
"small":{
"width":36,
"fileName":"nftrade-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":400,
"fileName":"nftrade-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":400
},
"full":{
"width":3000,
"fileName":"nftrade-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"NFTrade",
"chains":[
"moonbeam",
"moonriver"
],
"defiLLamaTvlExist":false,
"marketData":{
"symbol":"nftd",
"marketCap":234018,
"marketCapRank":3653,
"priceChangePercentage1y":-65.38449,
"currentPrice":0.00502075,
"priceChangePercentage14d":-7.09922,
"contracts":{
},
"priceChangePercentage60d":-27.37596,
"priceChangePercentage30d":-14.12267,
"priceChangePercentage24h":-2.22137,
"priceChangePercentage200d":-56.66993,
"marketCapChangePercentage24h":-2.16658,
"priceChange24h":-0.00011406326237191,
"marketCapChange24h":-5182.473845666,
"priceChangePercentage7d":-6.88049
},
"coinGeckoId":"nftrade",
"projectCreationDate":1644828523000,
"shortDescription":"Create, Buy, Sell, Swap and Farm NFTs",
"contracts":[
],
"updatedAt":1722548304198,
"category":"nfts",
"description":"NFTrade is a multi-chain platform for NFT creation and trading. Seamlessly launch, mint, and swap non-fungible tokens. Earn digital collectibles. NFTrade places you at the heart of the NFT economy. Create, Buy, Sell, Swap and Farm NFTs. All chains, All NFTs, One Platform.",
"id":"nftrade",
"tags":[
"NFT Marketplaces",
"MOVR Grants"
]
},
{
"urls":{
"website":"https://www.pipcards.com/",
"try":"https://www.pipcards.com/",
"twitter":"https://twitter.com/pipcards",
"discord":"https://discord.com/invite/hnSC7QjTHj"
},
"slug":"pipcards",
"createdAt":1699292616371,
"logo":{
"small":{
"width":36,
"fileName":"pipcards-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":400,
"fileName":"pipcards-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":400
},
"full":{
"width":3000,
"fileName":"pipcards-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"PIP Cards",
"chains":[
"moonriver"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1651149583000,
"shortDescription":"Post-generated NFT playing card decks",
"contracts":[
],
"updatedAt":1722498904704,
"category":"nfts",
"description":"PIPS is a first-of-its-kind NFT generative playing card project that will enable NFT holders to generate an entire deck of custom cards to be used cross-chain.",
"id":"pipcards",
"tags":[
"NFT",
"Gaming"
]
},
{
"urls":{
"website":"https://bithotel.io/",
"twitter":"https://twitter.com/playbithotel",
"github":"https://github.com/BitHotelOrg/bithotel-token-contracts",
"discord":"https://discord.gg/RFFZNwxY9n",
"telegram":"https://t.me/bithotelcommunity",
"try":"https://bithotel.io/",
"medium":"https://medium.com/@bithotelnftgame"
},
"slug":"bit-hotel",
"createdAt":1702283710425,
"logo":{
"small":{
"width":36,
"fileName":"bit-hotel-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":500,
"fileName":"bit-hotel-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":500
},
"full":{
"width":3000,
"fileName":"bit-hotel-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"Bit Hotel",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1658743551000,
"shortDescription":"Bit Hotel is a Social-first Play 2 Earn NFT Gaming Metaverse set in a Pixel-art Hotel.",
"contracts":[
{
"chain":"moonbeam",
"contract":"Not deployed yet"
},
{
"chain":"moonriver",
"contract":"Not deployed yet"
}
],
"updatedAt":1722498854706,
"category":"nfts",
"description":"In Bit Hotel users can compete to earn Bit Hotel tokens and acquire native NFTs. These NFTs have in-game utilities and consist of characters, hotel rooms, furniture and other assets that have their own unique perks. With over 250k Hotel Guests cross-channel, this nostalgic Hotel metaverse is taking people back to their 8bit upbringing.",
"id":"bit-hotel",
"tags":[
"NFT",
"Gaming"
]
},
{
"tvlChange7d":{
"moonriver":0.00190215150271202
},
"urls":{
"website":"https://www.moonbeamdao.com/",
"try":"https://www.moonbeamdao.com/",
"twitter":"https://twitter.com/moonbeam_dao",
"medium":"https://medium.com/@moonbeamdao",
"discord":"https://discord.gg/AevrFzwZjk"
},
"web3goContracts":[
{
"name":"MoonDAO: MDAO Token",
"chain":"moonbeam",
"contract":"0xc6342eab8b7cc405fc35eba7f7401fc400ac0709"
}
],
"currentTx":{
"moonbeam":972
},
"slug":"moondao",
"web3goIDs":[
"MoonDAO"
],
"createdAt":1699292616416,
"tvlChange1d":{
"moonriver":-0.0349944884006391
},
"logo":{
"small":{
"width":25,
"fileName":"moondao-logo-small.png",
"mimeType":"image/png",
"height":36
},
"large":{
"width":330,
"fileName":"moondao-logo-large.png",
"mimeType":"image/png",
"height":475
},
"full":{
"width":3000,
"fileName":"moondao-logo-full.png",
"mimeType":"image/png",
"height":3000
}
},
"name":"MoonDAO",
"chains":[
"moonbeam"
],
"currentTVL":{
"moonriver":76.75665
},
"currentUsers":{
"moonbeam":229
},
"projectCreationDate":1648347145000,
"shortDescription":"The first & only community art dao on moonbeam",
"contracts":[
],
"updatedAt":1722547637377,
"category":"nfts",
"description":"MoonDao is the first community Art Collection DAO on the Moonbeam network!\n\nWe aim to utilize input from our community to select high-end NFT’s. These NFT’s will be acquired with the MoonDao treasury and stored in the MoonDao Vault.\n\nMoon ownership grants access to DAO voting rights, future events, and additional holder perks outlined below. Welcome to the moon, we hope you stay.\n\n",
"id":"moondao",
"tags":[
"NFT",
"DAO"
]
},
{
"urls":{
"telegram":"https://t.me/raresama",
"website":"https://raresama.com/",
"try":"https://raresama.com/",
"twitter":"https://twitter.com/RaresamaNFT",
"discord":"https://discord.com/channels/938592318380982303/1010237900685840405"
},
"slug":"raresama",
"createdAt":1699292615958,
"logo":{
"small":{
"width":36,
"fileName":"raresama-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":400,
"fileName":"raresama-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":400
},
"full":{
"width":3000,
"fileName":"raresama-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"Raresama",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1662528828000,
"shortDescription":"Discover amazing Rare digital artwork",
"contracts":[
],
"updatedAt":1722498909462,
"category":"nfts",
"description":"Raresama brings the magic of owning a piece of artwork to your fingertips. Create or browse NFT art collections and enjoy a diverse mix of artists, genres, styles and movements.",
"id":"raresama",
"tags":[
"NFT Marketplaces"
]
},
{
"urls":{
"telegram":"https://gal.xyz/telegram",
"website":"https://galxe.com/",
"try":"https://galxe.com/",
"twitter":"https://twitter.com/Galxe",
"medium":"https://blog.galxe.com/",
"discord":"https://gal.xyz/discord"
},
"slug":"galxe",
"createdAt":1699292616277,
"logo":{
"small":{
"width":36,
"fileName":"galxe-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":400,
"fileName":"galxe-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":400
},
"full":{
"width":3000,
"fileName":"galxe-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"Galxe",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1659868871000,
"shortDescription":"Create Impactful Experiences With #Web3 Credentials. (Formerly Project Galaxy) ",
"contracts":[
],
"updatedAt":1722498876438,
"category":"nfts",
"description":"Galxe is the leading Web3 credential data network in the world. A collaborative credential infrastructure enabling brands and developers to engage communities and build robust products in Web3.",
"id":"galxe",
"tags":[
"NFT",
"Social",
"Tool"
]
},
{
"urls":{
"telegram":"http://t.me/MoonsamaNFT",
"website":"https://moonsama.com/",
"try":"https://moonsama.com/",
"twitter":"https://twitter.com/MoonsamaNFT",
"discord":"discord.gg/moonsama"
},
"slug":"moonsama",
"createdAt":1702283735408,
"logo":{
"small":{
"width":36,
"fileName":"moonsama-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":512,
"fileName":"moonsama-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":512
},
"full":{
"width":3000,
"fileName":"moonsama-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"Moonsama",
"chains":[
"moonriver",
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1651156798000,
"shortDescription":"Let's build the multiverse",
"contracts":[
],
"updatedAt":1722498892389,
"category":"nfts",
"description":"Moonsama’s protocol for bi-directional bridging of on-chain digital assets and off-chain applications. This is how we connect web2.0 games, metaverses and blockchains. It enables new games, development and community fun from across the Kusamaverse and beyond!",
"id":"moonsama",
"tags":[
"NFT",
"Gaming"
]
},
{
"urls":{
"website":"https://smartstamp.com/",
"try":"https://smartstamp.com/",
"discord":"https://discord.gg/kajPqvZY"
},
"slug":"smartstamp",
"createdAt":1699292617058,
"logo":{
"small":{
"width":36,
"fileName":"smartstamp-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":436,
"fileName":"smartstamp-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":436
},
"full":{
"width":3000,
"fileName":"smartstamp-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"SmartStamp",
"chains":[
"moonbeam",
"moonriver"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1675081766000,
"shortDescription":"SmartStamp is the pioneering new standard in identification and authentication for the art world.",
"contracts":[
],
"updatedAt":1722498915044,
"category":"nfts",
"description":"Developed over more than a decade, SmartStamp’s app uses patented AI technology that is designed to read and record artworks’ surface characteristics– offering artists, collectors, institutions, and all arts and culture stakeholders a way to securely and immutably link physical objects to their digital fingerprints on the blockchain. Using the SmartStamp app is as simple as taking a picture, making the groundbreaking security and timestamping power of blockchain technology accessible to anyone who can use a smartphone.",
"id":"smartstamp",
"tags":[
"NFT"
]
},
{
"urls":{
"telegram":"https://t.me/yusernetwork",
"website":"https://yuser.network/",
"try":"https://yuser.network/",
"twitter":"https://twitter.com/yuser",
"medium":"https://medium.com/yuser",
"discord":"https://discord.com/invite/uRRxnfAjhY"
},
"slug":"yuser",
"createdAt":1699292616605,
"logo":{
"small":{
"width":36,
"fileName":"yuser-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":512,
"fileName":"yuser-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":512
},
"full":{
"width":3000,
"fileName":"yuser-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"Yuser",
"chains":[
"moonriver"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1644828523000,
"shortDescription":"The first NFT social networking app- by creators, for creators",
"contracts":[
],
"updatedAt":1722498932483,
"category":"nfts",
"description":"Yuser’s mission is to build an ecosystem of interconnected applications that put power back into the hands of users by giving them full control over their content, data, and personal networks. Developers can connect via an API to instantly gain access to millions of users and incentivize them to try their product by paying them with a token.",
"id":"yuser",
"tags":[
"NFT Marketplaces",
"GLMR Grants",
"MOVR Grants"
]
},
{
"urls":{
"telegram":"https://t.me/cryptosoots",
"website":"https://raregems.io/my#",
"try":"https://raregems.io/my#",
"twitter":"https://twitter.com/RareGems_io"
},
"slug":"rare-gems",
"createdAt":1702283745336,
"logo":{
"small":{
"width":36,
"fileName":"rare-gems-logo-small.png",
"mimeType":"image/png",
"height":36
},
"large":{
"width":360,
"fileName":"rare-gems-logo-large.png",
"mimeType":"image/png",
"height":360
},
"full":{
"width":3000,
"fileName":"rare-gems-logo-full.png",
"mimeType":"image/png",
"height":3000
}
},
"name":"Rare Gems",
"chains":[
"moonriver",
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1652705611000,
"shortDescription":"Multichain NFT marketplace.",
"contracts":[
],
"updatedAt":1722498909205,
"category":"nfts",
"description":"Multichain NFT marketplace\nCreated by \n@cryptosoots",
"id":"rare-gems",
"tags":[
"NFT Marketplaces"
]
},
{
"urls":{
"telegram":"https://t.me/rmrkapp",
"website":"https://wizard.rmrk.dev",
"try":"https://wizard.rmrk.dev",
"twitter":"https://x.com/rmrkapp",
"github":"https://github.com/rmrk-team",
"medium":"https://medium.com/rmrkapp"
},
"slug":"rmrk-wizard",
"createdAt":1699292616919,
"logo":{
"small":{
"width":36,
"fileName":"rmrk-wizard-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":512,
"fileName":"rmrk-wizard-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":512
},
"full":{
"width":3000,
"fileName":"rmrk-wizard-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"RMRK Wizard",
"chains":[
"moonbeam",
"moonriver"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1692255253000,
"shortDescription":"A no-code-but-code wizard UI for building NFTs 2.0",
"contracts":[
],
"updatedAt":1722498911520,
"category":"nfts",
"description":"A simple UI to put together NFT 2.0 legos created by the RMRK.app team. Use this tool to get started developing advanced NFT collections by picking from a set of functions you need, and the tool will compose code for you which only needs final tweaks before being deployed!",
"id":"rmrk-wizard",
"tags":[
"NFT",
"Tool",
"Developer Tools"
]
},
{
"urls":{
"telegram":"https://t.me/evelonapp",
"website":"https://platform.evelon.app/",
"try":"https://www.evelon.app/",
"twitter":"https://twitter.com/EvelonApp"
},
"slug":"evelon-app",
"createdAt":1699292616145,
"logo":{
"small":{
"width":36,
"fileName":"evelon-app-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":512,
"fileName":"evelon-app-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":512
},
"full":{
"width":3000,
"fileName":"evelon-app-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"Evelon.App",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1690486894000,
"shortDescription":"Transform the way you create and bring to life your own unique DNFTs, with the revolutionary platform that combines cutting-edge AI technology.",
"contracts":[
],
"updatedAt":1722498873048,
"category":"nfts",
"description":"Evelon is a no code platform that allows you to create and deploy dynamic NFTs with ease. This project is a game changer in the world of NFTs and image generation. Evelon uses AI to generate high-quality images, making it possible to create NFTs with unique visuals that are both dynamic and engaging.",
"id":"evelon-app",
"tags":[
"NFT",
"Tool"
]
},
{
"urls":{
"website":"https://mintlabz.io/",
"try":"https://app.mintlabz.io/",
"twitter":"https://twitter.com/mintlabz",
"medium":"https://blog.mintlabz.io/",
"discord":"https://discord.com/invite/BRF2PEetea"
},
"slug":"mintlabz",
"createdAt":1712311518649,
"logo":{
"small":{
"width":36,
"fileName":"mintlabz-logo-small.png",
"mimeType":"image/png",
"height":36
},
"large":{
"width":400,
"fileName":"mintlabz-logo-large.png",
"mimeType":"image/png",
"height":400
},
"full":{
"width":3000,
"fileName":"mintlabz-logo-full.png",
"mimeType":"image/png",
"height":3000
}
},
"name":"Mintlabz",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1712189524,
"shortDescription":"MintLabz is a complete crosschain NFT solution at zero cost.",
"contracts":[
],
"updatedAt":1722498889042,
"category":"nfts",
"description":"MintLabz aims to establish a digital NFT minting platform for third party projects to create NFT collections with utilities to reward the NFT holder. Our mission is to become the number one choice for providing complete cross-chain NFT solutions to B2B customers.",
"id":"mintlabz",
"tags":[
"nfts"
]
},
{
"urls":{
"telegram":"https://t.me/golempark",
"website":"https://golempark.com",
"try":"https://golempark.com",
"twitter":"https://twitter.com/golempark",
"discord":"https://discord.gg/rNvtdHN8q7"
},
"slug":"golem-park",
"createdAt":1699292617039,
"logo":{
"small":{
"width":36,
"fileName":"golem-park-logo-small.png",
"mimeType":"image/png",
"height":36
},
"large":{
"width":512,
"fileName":"golem-park-logo-large.png",
"mimeType":"image/png",
"height":512
},
"full":{
"width":3000,
"fileName":"golem-park-logo-full.png",
"mimeType":"image/png",
"height":3000
}
},
"name":"Golem Park",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1676839105000,
"shortDescription":"Golem Park is holders friendly NFT collection. P2E blockchain game, $GP Token, Staking Pools & more",
"contracts":[
{
"chain":"moonbeam",
"contract":"0x74746524f5A31F08e0528FaA704C2c5d8d116506"
}
],
"updatedAt":1722498878088,
"category":"nfts",
"description":"First Time In Crypto History Token Burning Campaign!\n30% Of Total Token Supply Will Be Burned In 30 Days.\n\nAfter Minting We Are Going To Release Deflationary $GP Token & 50% Of Total Supply Will Be Distributed To All $GP NFT Holders, 1 NFT = 5 000 000 Tokens. Then 30 Days Each Day We'll Burn 1% Of Total Token Supply To Ensure Token Price Will Go UP!\n\nWorld Of Golems is a decentralized Play-To-Earn blockchain game.\nOnce You Become Golem Park NFT Holder You Will Be Able To Participate in the WoG Game, Own Countries And Display Your Message On Them.\n\nThe Leaderboard Shows Of TOP 5 Wealthiest Countries & Every Month Owners Of These Countries Will Be Rewarded With $GLMR.",
"id":"golem-park",
"tags":[
"NFT"
]
},
{
"urls":{
"telegram":"https://t.me/rarible",
"website":"https://rarible.com/",
"try":"https://rarible.com/",
"twitter":"https://x.com/rarible",
"discord":"https://discord.com/invite/rarible"
},
"slug":"rarible",
"createdAt":1722498909701,
"logo":{
"small":{
"width":429,
"fileName":"rarible-small.png",
"mimeType":"image/png",
"height":121
},
"large":{
"width":858,
"fileName":"rarible-medium.png",
"mimeType":"image/png",
"height":242
},
"full":{
"width":1716,
"fileName":"rarible-large.png",
"mimeType":"image/png",
"height":485
}
},
"name":"Rarible",
"chains":[
"moonbeam"
],
"shortDescription":"Rarible - NFT Marketplace for Brands, Communities and Traders",
"projectCreationDate":1721872843,
"contracts":[
],
"updatedAt":1722498909701,
"category":"nfts",
"description":"Discover, sell and buy NFTs on Rarible! Our aggregated NFT marketplace for Ethereum NFTs and Polygon NFTs powers brands, collections and creator marketplaces.",
"id":"rarible",
"featured":false,
"tags":[
"NFT"
]
},
{
"urls":{
"website":"https://neoncrisis.io/",
"try":"https://neoncrisis.io/",
"twitter":"https://twitter.com/NeonCrisisNFT",
"discord":"https://discord.gg/MVVjT9k9eD"
},
"slug":"neoncrisis-io",
"createdAt":1702283737907,
"logo":{
"small":{
"width":36,
"fileName":"neoncrisis-io-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":319,
"fileName":"neoncrisis-io-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":319
},
"full":{
"width":3000,
"fileName":"neoncrisis-io-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"Neon Crisis",
"chains":[
"moonriver"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1654792548000,
"shortDescription":"6,008 heroes on the $MOVR network. A $RMRK powered metaverse featuring battle simulations, equipables, and more!",
"contracts":[
],
"updatedAt":1722498896060,
"category":"nfts",
"description":"",
"id":"neoncrisis-io",
"tags":[
"NFT",
"Gaming"
]
},
{
"urls":{
"telegram":"https://t.me/xp_network",
"website":"https://xp.network/",
"try":"https://xp.network/",
"twitter":"https://twitter.com/xpnetwork_",
"discord":"https://discord.com/invite/g3vkcsmd38"
},
"slug":"xp-network",
"createdAt":1699292615205,
"logo":{
"small":{
"width":36,
"fileName":"xp-network-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":400,
"fileName":"xp-network-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":400
},
"full":{
"width":3000,
"fileName":"xp-network-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"XP Network",
"chains":[
"moonbeam"
],
"defiLLamaTvlExist":false,
"projectCreationDate":1673327644000,
"shortDescription":"A powerful NFT bridge trusted by all major blockchains ",
"contracts":[
],
"updatedAt":1722498932103,
"category":"nfts",
"description":"We build software tools that enable experienced developers and non-coding blockchain community members to move their assets seamlessly and intuitively between versatile distributed ledgers. By doing so, we encourage unlimited growth of exchange and trade between otherwise isolated ecosystems. We enable them to enrich each other technologically with insights and discoveries. To gain access to new, previously inaccessible markets with users hungry for fresh ideas and technologies to invest in.",
"id":"xp-network",
"tags":[
"NFT",
"Bridges"
]
},
{
"urls":{
"website":"https://www.damnedpiratessociety.io/",
"try":"https://www.damnedpiratessociety.io/",
"twitter":"https://twitter.com/TheDPSproject",
"discord":"https://discord.com/invite/TheDamnedPiratesSociety"
},
"web3goContracts":[
{
"name":"Damned Pirates Society: DPSArtifact Token",
"chain":"moonriver",
"contract":"0xcd84ddadc45a25b02e1a6a5520171487a98e6155"
},
{
"name":"Damned Pirates Society: DPS Token",
"chain":"moonriver",
"contract":"0xb6e9e605aa159017173caa6181c522db455f6661"
},
{
"name":"Damned Pirates Society: DSPFlagship Token",
"chain":"moonriver",
"contract":"0x3822063a3f1aad3fd0b894e2a8f238ccca7c2d00"
},
{
"name":"Damned Pirates Society: DSPVoyage Token",
"chain":"moonriver",
"contract":"0x7b2e778453ab3a0d946c4620fb38a0530a434e15"
},
{
"name":"Damned Pirates Society: DOUBLOON Token",
"chain":"moonriver",
"contract":"0xe413a631e8a9a10958d9b7c64157449eae7c2064"
}
],
"currentTx":{
"moonriver":20402
},
"slug":"damned-pirates-society",
"web3goIDs":[
"Damned Pirates Society"
],
"createdAt":1699292616058,
"logo":{
"small":{
"width":36,
"fileName":"damned-pirates-society-logo-small.jpeg",
"mimeType":"image/jpeg",
"height":36
},
"large":{
"width":400,
"fileName":"damned-pirates-society-logo-large.jpeg",
"mimeType":"image/jpeg",
"height":400
},
"full":{
"width":3000,
"fileName":"damned-pirates-society-logo-full.jpeg",
"mimeType":"image/jpeg",
"height":3000
}
},
"name":"Damned Pirates Society",
"chains":[
"moonriver"
],
"defiLLamaTvlExist":false,
"currentUsers":{
"moonriver":2000
},
"projectCreationDate":1644828523000,
"shortDescription":"Eclectic pirate-based NFT project with utility",
"contracts":[
],
"updatedAt":1722547421801,
"category":"nfts",
"description":"A long time ago the Fortune’s Grasp was carrying families to settle on The Islands and start a new life. In the middle of their voyage they encountered a fearsome maelstrom. The Captain and his crew worked tirelessly to keep the ship afloat. Badly damaged, the Ship limped to the edges of the storm. It was taking on water and the cries of terrified children could be heard above the crashing waves. Another ship appeared on the horizon, it’s light glowing brightly against the dark night. The Captain of the Fortune’s Grasp ordered his crew to evacuate the families, but the fifty crew members ignored the Captain, abandoning ship, taking all means of escape with them. The Captain, left on the sinking ship, cursed the cowardly crew for damning those innocent souls to the watery depths. Those Forsaken Fifty were marked with The Black Spot, doomed to row the high seas until the Reaper came to claim his mutinous crew to serve on the Ship Of The Damned. However, if they could convince another soul to take their place at the oars, protection would be offered by those Pirates who’ve cheated the Reaper before. Those who’ve served and survived are welcome in the Damned Pirates Society.\r\n\r\nThe Damned Pirate Society is an Profile Picture NFT with inbuilt utility. Stake your Pirate for Treasure Maps(TMAP) and save these for your Doubloon farming voyages on our upcoming, skill based gamified contracts.",
"id":"damned-pirates-society",
"tags":[
"NFT",
"Gaming",
"GLMR Grants"
]
}
],
"count":40
}
```
Below are all possible categories and their respective parameters for querying the API. Ensure you query the API with the parameter formatted exactly as shown in lowercase.
| Category | API Parameter |
|:--------:|:-------------:|
| Bridges | `bridges` |
| DAO | `dao` |
| DEX | `dex` |
| DeFi | `defi` |
| Gaming | `gaming` |
| Lending | `lending` |
| NFTs | `nfts` |
| Other | `other` |
| Social | `social` |
| Wallets | `wallets` |
### Query a Chain {: #query-a-chain}
The following queries can be used to query all of the listed projects on Moonbeam or Moonriver. Note that Moonbase Alpha is not a supported network in the DApp Directory.
=== "Moonbeam"
```bash
https://apps.moonbeam.network/api/ds/v1/app-dir/projects?chain=moonbeam
```
=== "Moonriver"
```bash
https://apps.moonbeam.network/api/ds/v1/app-dir/projects?chain=moonriver
```
You are responsible for checking and validating the accuracy and truthfulness of all content. You are also responsible for doing your own diligence to understand the applicable risks present, including selection, performance, security, accuracy, or use of any third-party information. All information contained herein is subject to modification without notice.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/learn/platform/glossary/
--- BEGIN CONTENT ---
---
title: Glossary
description: We've compiled a glossary of terms related to Polkadot that'll make it easier to learn more about the ecosystem.
categories: Reference
---
# Glossary
There's a great deal of terminology that's specific to Polkadot, Substrate, and the emerging Parity/Web3 ecosystem. We've compiled a list of terms we think you'll want to know as you review the Moonbeam documentation, plans, and tutorials.
### Collators {: #collators }
One of the key network participants needed to support parachains within the Polkadot Network. In Moonbeam, collators are the nodes that are responsible for block production and for submitting produced blocks up to the Polkadot relay chain for finalization.
### Delegators {: #delegators }
Moonbeam token holders who stake tokens, vouching for specific collator candidates on the parachain. Any user that holds a minimum amount of tokens as [free balance](https://wiki.polkadot.com/learn/learn-accounts/#balance-types#balance-types){target=\_blank} can become a delegator by staking their tokens.
### Nominators {: #nominators }
Relay chain token holders who select to "back" a validator. They can receive part of the validator's reward, but are subject to slashing of their staked tokens in case the validator misbehaves. A nominator can back up to 16 validators, and their bond is fully distributed between the backed validators that were selected for the validator set.
### Nominated Proof of Stake {: #nominated-proof-of-stake }
The mechanism used by Polkadot for selecting its block validator set to maximize chain security. At its core, it is a Proof-of-Stake system (PoS) in which nominators back validators. The latter with the highest backing are selected to be part of the validator set for a session. The stake of a validator is slashed in case of misbehavior. Thus, nominators are expected to do due diligence on the validators they nominate.
### Parachains {: #parachains }
A blockchain which has a slot and is connected to Polkadot. Parachains receive shared security from Polkadot and the ability to interact with other parachains on the Polkadot network. They must lock DOT, the native relay chain token, to secure a slot for a specific period (up two years).
### Parathreads {: #parathreads }
A blockchain which can connect to Polkadot. Parathreads are able to interact with other members of the Polkadot network, but they bid for block finalization (in DOT) on a block-to-block basis. They compete with other parathreads for block finalization, meaning that the block with the highest bid is selected to be finalize in that round.
### Polkadot {: #polkadot }
A network of connected blockchains that provides shared security and the ability to interact between chains. Polkadot is built using the Substrate development framework. Chains that connect to Polkadot are called parachains.
### Relay Chain {: #relay-chain }
The backbone blockchain supporting the Polkadot network. Parachains connect to the relay chain and use it for shared security and message passing. Validators on the relay chain help secure the parachains.
### Smart Contract {: #smart-contract }
A [smart contract](https://en.wikipedia.org/wiki/Smart_contract){target=\_blank} is a computer program or a transaction protocol that is intended to automatically execute, control, or document legally relevant events and actions according to the terms of a contract or an agreement. Smart contracts intend to reduce the need for trusted intermediators, arbitrations, and enforcement costs, as well as reduce fraud losses and malicious and accidental exceptions.
### Substrate {: #substrate }
A Rust-based blockchain development framework created by Parity Technologies based on their experience implementing multiple blockchain clients. Substrate comes with many modules and functionalities that are needed when building a blockchain, including P2P networking, consensus mechanisms, staking, cryptocurrency, on-chain governance modules, and more. It dramatically reduces the time and engineering effort required to implement a blockchain. Substrate is now part of the [Polkadot SDK](https://polkadot.com/platform/sdk/){target=\_blank}.
### Substrate Frame Pallets {: #substrate-frame-pallets }
Substrate Frame Pallets are a collection of Rust-based modules, providing the functionality required for building a blockchain.
### Validators {: #validators }
A node that secures the Polkadot relay chain by staking DOT in the network, which is slashed if they misbehave. They finalize blocks from collators on parachains and also participate on consensus for the next relay chain block with other validators.
### WebAssembly/Wasm {: #webassemblywasm }
WebAssembly is an open standard that defines a portable binary code format. It is supported by different programming languages, compilers, and browsers.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/build/historical-updates/
--- BEGIN CONTENT ---
---
title: Historical Updates
description: An overview of the historical updates made on Moonbeam and Moonriver, such as migrations and bug fixes applied to the Moonbeam source code.
categories: Reference
---
# Historical Updates
## Introduction {: #introduction }
This page overviews historical updates on Moonbeam and Moonriver, such as bug fixes to the Moonbeam source code and data migrations applied.
This page aims to provide information about unexpected behaviors or data inconsistencies associated with updates that require forced data migrations.
## Bugs {: #bugs }
#### Invalid Transactions Stored {: #invalid-transactions-stored }
For invalid transactions where the transaction cost couldn't be paid, the EVM pallet inserted the transaction metadata into storage instead of discarding it because there was no transaction cost validation. As a result, the runtime storage was unnecessarily bloated with invalid transaction data.
This bug only impacted Moonriver and Moonbase Alpha and existed during the following runtimes and block ranges:
| Network | Introduced | Fixed | Impacted Block Range |
|:--------------:|:----------:|:-----:|:--------------------:|
| Moonriver | RT49 | RT600 | 0 - 455106 |
| Moonbase Alpha | RT40 | RT600 | 0 - 675175 |
For more information, you can review the [relative Frontier PR on GitHub](https://github.com/polkadot-evm/frontier/pull/465){target=\_blank}.
---
#### Ethereum Fees Weren't Sent to Treasury {: #ethereum-fees-to-treasury }
The Moonbeam transaction fee model before Runtime 3401 and the passage of [MB101](https://forum.moonbeam.network/t/proposal-mb101-burn-100-of-transaction-fees-on-moonbeam/2022){target=\_blank} mandated a 20% allocation of fees sent to the on-chain Treasury and 80% burned as a deflationary force. However, before runtime 800, Ethereum transactions did not correctly allocate 20% of the transaction fees to the on-chain Treasury.
This bug only impacted Moonriver and Moonbase Alpha and existed during the following runtimes and block ranges:
| Network | Introduced | Fixed | Impacted Block Range |
|:--------------:|:----------:|:-----:|:--------------------:|
| Moonriver | RT49 | RT800 | 0 - 684728 |
| Moonbase Alpha | RT40 | RT800 | 0 - 915684 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/732){target=\_blank}.
---
#### Missing Refunds {: #missing-refunds }
Moonbeam is configured to set the existential deposit to 0, meaning that accounts do not need a minimum balance to be considered active. For Substrate-based chains with this configuration, some refunds were missing from zeroed accounts because the account was interpreted as not existing.
This bug existed during the following runtimes and block ranges:
| Network | Introduced | Fixed | Impacted Block Range |
|:--------------:|:----------:|:------:|:--------------------:|
| Moonbeam | RT900 | RT1001 | 0 - 5164 |
| Moonriver | RT49 | RT1001 | 0 - 1052241 |
| Moonbase Alpha | RT40 | RT1001 | 0 - 1285915 |
For more information, you can review the [relative Frontier PR](https://github.com/polkadot-evm/frontier/pull/509){target=\_blank} and the associated [Substrate PR on GitHub](https://github.com/paritytech/substrate/issues/10117){target=\_blank}.
---
#### Incorrect Collator Selection {: #incorrect-collator-selection }
The total delegations for collator candidates were not correctly updated when a delegation was increased via the `delegatorBondMore` extrinsic. This led to issues where the increased delegation amount wasn't included in the candidates' total amount bonded, which is used to determine which candidates are in the active set of collators. As a result, some candidates may not have been selected to be in the active set when they should have been, impacting their own and their delegators' rewards.
This bug existed during the following runtimes and block ranges:
| Network | Introduced | Fixed | Impacted Block Range |
|:--------------:|:----------:|:------:|:--------------------:|
| Moonbeam | RT900 | RT1300 | 0 - 524762 |
| Moonriver | RT49 | RT1300 | 0 - 1541735 |
| Moonbase Alpha | RT40 | RT1300 | 0 - 1761128 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1291){target=\_blank}.
---
#### New Account Event Bug {: #new-account-event }
The `System.NewAccount` event is emitted when a new account is created. However, a bug prevented this event from being emitted for some accounts at creation time. A hotfix was applied that patched the impacted accounts and emitted the `System.NewAccount` at a later time.
The hotfix was applied in the following block ranges:
| Network | Block Range |
|:--------------:|:-------------------------------------------------------------------------------------------------------------------------------------:|
| Moonbeam | [1041355 - 1041358 and 1100752](https://moonbeam.subscan.io/extrinsic?module=evm&call=hotfix_inc_account_sufficients){target=\_blank} |
| Moonriver | [1835760 - 1835769](https://moonriver.subscan.io/extrinsic?module=evm&call=hotfix_inc_account_sufficients){target=\_blank} |
| Moonbase Alpha | [2097782 - 2097974](https://moonbase.subscan.io/extrinsic?address=&module=evm&call=hotfix_inc_account_sufficients){target=\_blank} |
This bug existed during the following runtimes and block ranges:
| Network | Introduced | Fixed | Impacted Block Range |
|:--------------:|:----------:|:------:|:--------------------:|
| Moonbeam | RT900 | RT1401 | 0 - 915320 |
| Moonriver | RT49 | RT1401 | 0 - 1705939 |
| Moonbase Alpha | RT40 | RT1400 | 0 - 1962557 |
For more information, you can review the [relative Frontier PR on GitHub](https://github.com/moonbeam-foundation/frontier/pull/46/files){target=\_blank}.
---
#### Incorrect Timestamp Units {: #incorrect-timestamp-units }
EIP-2612 and Ethereum blocks deal with timestamps in seconds; however, the Substrate timestamp pallet that Moonbeam implements uses milliseconds. This only affected the EIP-2612 implementation, not the `block.timestamp` value.
This bug existed during the following runtimes and block ranges:
| Network | Introduced | Fixed | Impacted Block Range |
|:--------------:|:----------:|:------:|:--------------------:|
| Moonbeam | RT900 | RT1606 | 0 - 1326697 |
| Moonriver | RT49 | RT1605 | 0 - 2077598 |
| Moonbase Alpha | RT40 | RT1603 | 0 - 2285346 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1451){target=\_blank}.
---
#### Substrate Tips Missing Treasury Distribution {: #substrate-tips }
Tips for Substrate-based transactions weren't handled properly. The entire portion of the tip was burned because it was not handled in the runtime code. A fix was applied so that 20% was paid to the Treasury and 80% was burned, consistent with all other fee behavior at that time.
Note that RT3401 introduced a parameters pallet fee configuration allowing governance to adjust how fees are split between the Treasury and burning. After this runtime upgrade combined with the passage of [MB101](https://forum.moonbeam.network/t/proposal-mb101-burn-100-of-transaction-fees-on-moonbeam/2022){target=\_blank}, 100% of all transaction fees on both Moonbeam and Moonriver are now burned.
This bug existed during the following runtimes and block ranges:
| Network | Introduced | Fixed | Impacted Block Range |
|:--------------:|:----------:|:------:|:--------------------:|
| Moonbeam | RT900 | RT2403 | 0 - 4163078 |
| Moonriver | RT49 | RT2401 | 0 - 4668844 |
| Moonbase Alpha | RT40 | RT2401 | 0 - 4591616 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/2291){target=\_blank}.
---
#### Incorrect Delegation Reward Calculation {: #incorrect-delegation-reward-calculation }
The reward payouts for all delegations and collators were underestimated whenever there were pending requests. Delegation rewards are calculated based on the amount of tokens bonded by each delegator with respect to the total stake of the given collator. By counting delegation amounts for pending requests, the rewards to collators and their delegations were less than they should have been.
This bug existed during the following runtimes and block ranges:
| Network | Introduced | Fixed | Impacted Block Range |
|:--------------:|:----------:|:------:|:--------------------:|
| Moonbeam | RT1001 | RT1802 | 5165 - 1919457 |
| Moonriver | RT1001 | RT1801 | 1052242 - 2572555 |
| Moonbase Alpha | RT1001 | RT1800 | 1285916 - 2748785 |
You can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1719){target=\_blank} for more information.
---
#### Block Parent Hash Calculated Incorrectly {: #block-parent-hash-calculated-incorrectly }
After EIP-1559 support was introduced, which included the transition to new Ethereum transaction types, the block header parent hash was miscalculated to `H256::default`.
This bug only impacted Moonbase Alpha and only impacted the following block:
| Network | Introduced | Fixed | Impacted Block |
|:--------------:|:----------:|:------:|:--------------:|
| Moonbase Alpha | RT1200 | RT1201 | 1648995 |
While the root issue was fixed in RT1201, the incorrect hash was corrected in RT2601.
For more information on the root fix, you can review the [relative Frontier PR on GitHub](https://github.com/polkadot-evm/frontier/pull/570/){target=\_blank}. To take a look at the correction of the parent hash, check out the corresponding [Moonbeam PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/2524){target=\_blank}.
---
#### Incorrect Handling of EIP-1559 Gas Fees {: #incorrect-gas-fees-eip1559 }
With the introduction of EIP-1559 support, the logic for handling `maxFeePerGas` and `maxPriorityFeePerGas` was implemented incorrectly. As a result, the `maxPriorityFeePerGas` was added to the `baseFee` even if the total amount was over the `maxFeePerGas`.
This bug existed during the following runtimes and block ranges:
| Network | Introduced | Fixed | Impacted Block Range |
|:--------------:|:----------:|:------:|:--------------------:|
| Moonbeam | RT1201 | RT1401 | 415946 - 915320 |
| Moonriver | RT1201 | RT1401 | 1471037 - 1705939 |
| Moonbase Alpha | RT1200 | RT1400 | 1648994 - 1962557 |
For more information, you can review the [relative Frontier PR](https://github.com/moonbeam-foundation/frontier/pull/45){target=\_blank}.
---
#### Transaction Fees Paid to Collators {: #transaction-fees-paid-to-collators }
For blocks that included EIP-1559 transactions where a priority fee was applied, the transaction fees were incorrectly calculated and distributed to the block's collator. The fee model on Moonbeam for transactions and smart contract execution was previously handled so that 20% of the fees went to the on-chain Treasury and 80% were burned as a deflationary force. Due to this bug, the transaction fees of the impacted transactions were not burned as expected.
Note that RT3401 introduced a parameters pallet fee configuration allowing governance to adjust how fees are split between the Treasury and burning. After this runtime upgrade combined with the passage of [MB101](https://forum.moonbeam.network/t/proposal-mb101-burn-100-of-transaction-fees-on-moonbeam/2022){target=\_blank}, 100% of all transaction fees on both Moonbeam and Moonriver are now burned.
This bug existed during the following runtimes and block ranges:
| Network | Introduced | Fixed | Impacted Block Range |
|:--------------:|:----------:|:------:|:--------------------:|
| Moonbeam | RT1201 | RT1504 | 415946 - 1117309 |
| Moonriver | RT1201 | RT1504 | 1471037 - 1910639 |
| Moonbase Alpha | RT1200 | RT1504 | 1648994 - 2221772 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1528){target=\_blank}.
---
#### Incorrect State Root Hash {: #incorrect-state-root-hash }
The state root hash was miscalculated for non-legacy transactions as the transaction-type byte was not considered. With the support of [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930){target=\_blank} and [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559){target=\_blank}, the transaction types introduced are `0x01` (1) and `0x02` (2), respectively. These transaction types were omitted from the state root hash calculation.
This bug existed during the following runtimes and block ranges:
| Network | Introduced | Fixed | Impacted Block Range |
|:--------------:|:----------:|:------:|:--------------------:|
| Moonbeam | RT1201 | RT1701 | 415946 - 1581456 |
| Moonriver | RT1201 | RT1701 | 1471037 - 2281722 |
| Moonbase Alpha | RT1200 | RT1700 | 1648994 - 2529735 |
For more information, you can review the [relative Frontier PR](https://github.com/moonbeam-foundation/frontier/pull/86){target=\_blank} and [Moonbeam PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1678/files){target=\_blank}.
---
#### Ethereum Transactions Duplicated in Storage {: #ethereum-transactions-duplicated-in-storage }
An upstream bug was introduced to Frontier in the Ethereum Pallet, causing pending transactions that existed during a runtime upgrade to be duplicated in storage across two different blocks. This only impacted the first two blocks after the runtime upgrade in which this bug was introduced.
Only Moonriver and Moonbase Alpha were impacted. The bug was introduced in the following runtimes and affected the following blocks:
| Network | Introduced | Impacted Blocks |
|:--------------:|:----------:|:-------------------:|
| Moonriver | RT1605 | 2077599 and 2077600 |
| Moonbase Alpha | RT1603 | 2285347 and 2285348 |
The following transactions were duplicated:
=== "Moonriver"
```js
'0x2cceda1436e32ae3b3a2194a8cb5bc4188259600c714789bae1fedc0bbc5125f',
'0x3043660e35e89cafd7b0e0dce9636f5fcc218fce2a57d1104cf21aabbff9a1c0',
'0x514411fb5c08f7c5aa6c61c38f33edfa74ff7e160831f6140e8dd3783648dbca',
'0xf1647c357d8e1b05c522d11cff1f5090a4df114595d0f4b9e4ac5bb746473eea',
'0x4be94803fe7839d5ef13ddd2633a293b4a7dddbe526839c15c1646c72e7b0b23',
'0x15fceb009bd49692b598859f9146303ed4d8204b38e35c147fcdb18956679dbe',
'0xa7460d23d5c633feec3d8e8f4382240d9b71a0d770f7541c3c32504b5403b70c',
'0x1c838b4c4e7796a9db5edfd0377aee6e0d89b623bf1d7803f766f4cf71daefb9',
'0xfb233a893e62d717ed627585f14b1ee8b3e300ac4e2c3016eb63e546a60820f0',
'0xfaf8908838683ad51894eb3c68196afb99ba2e2bb698a40108960ee55417b56a',
'0xa53973acbeac9fe948015dcfad6e0cb28d91b93c8115347c178333e73fd332d3',
'0x9df769c96c5fdd505c67fee27eaff3714bf8f3d45a2afc02dd2984884b3cecac',
'0x8f912ae91b408f082026992a87060ed245dac6e382a84288bd38fc08dbac30fe',
'0xb22af459d24cb25bc53785bdd0ae6a573e24f226c94fd8d2e4663b87d3b07a88',
'0x8ab9cd2bde7d679f798528b0c75325787f5fc7997e00589445b35b3954a815aa',
'0xd08a1f82f4d3dc553b4b559925f997ef8bb85cb24cb4d0b893f017129fb33b78',
'0xa1d40bce7cc607c19ca4b37152b6d8d3a408e3de6b9789c5977fcdef7ef14d97',
'0xe442227634db10f5d0e8c1da09f8721c2a57267edbf97c4325c4f8432fd48ade',
'0x0b4f5d8338a7c2b1604c1c42e96b12dc2a9d5ab264eb74ff730354e9765de13f',
'0x0b00fc907701003aad75560d8b1a33cbf4b75f76c81d776b8b92d20e1d2e9d31',
'0x9c18bd783f28427d873970ff9deaf1549db2f9a76e3edd6bdeae11358e447ef4',
'0x8b2523f163989969dd0ebcac85d14805756bc0075b89da1274fd2c53ccaa396a',
'0x47e80a0c533265974a55ea62131814e31b10f42895709f7e531e3e7b69f1387c'
```
=== "Moonbase Alpha"
```js
'0x006a6843eb35ad35a9ea9a99affa8d81f1ed500253c98cc9c080d84171a0afb3',
'0x64c102f664eb435206ad4fcb49b526722176bcf74801c79473c3b5b2c281a243',
'0xf546335453b6e35ce7e236ee873c96ba3a22602b3acc4f45f5d68b33a76d79ca',
'0x4ed713ccd474fc33d2022a802f064cc012e3e37cd22891d4a89c7ba3d776f2db',
'0xa5355f86844bb23fe666b10b509543fa377a9e324513eb221e0a2c926a64cae4',
'0xc14791a3a392018fc3438f39cac1d572e8baadd4ed350e0355d1ca874a169e6a'
```
The duplicated transactions belong to the first block. So, on Moonriver, the transactions belong to block 2077599, and on Moonbase Alpha, the impacted transactions belong to block 2285347.
For more information, you can review the [relative Frontier PR on GitHub](https://github.com/polkadot-evm/frontier/pull/638){target=\_blank}.
---
#### Gas Limit Too High for Non-Transactional Calls {: #gas-limit-too-high-for-non-transactional-calls }
When a non-transactional call, such as `eth_call` or `eth_estimateGas`, is made without specifying a gas limit for a past block, the client defaults to using the gas limit multiplier (10x), which causes the gas limit validation to fail as it is validating against an upper bound of the block gas limit. So, if the gas limit is greater than the block gas limit for a given call, a gas limit too high error is returned.
This bug existed during the following runtimes and block ranges:
| Network | Introduced | Fixed | Impacted Block Range |
|:--------------:|:----------:|:------:|:--------------------:|
| Moonbeam | RT1701 | RT1802 | 1581457 - 1919457 |
| Moonriver | RT1701 | RT1802 | 2281723 - 2616189 |
| Moonbase Alpha | RT1700 | RT1802 | 2529736 - 2879402 |
You can review the [relative Frontier PR on GitHub](https://github.com/polkadot-evm/frontier/pull/935){target=\_blank} for more information.
---
#### Remote EVM Calls Return Identical Transaction Hashes {: #remote-evm-calls-return-identical-tx-hashes }
When multiple remote EVM calls were sent from different accounts with the same transaction payload and nonce, the same transaction hash was returned for each call. This was possible because remote EVM calls are executed from a keyless account, so if the senders all had the same nonce and were sending the same transaction object, there was no differentiation in the calculation of the transaction hash. This was fixed by adding a global nonce to the Ethereum XCM Pallet, which is the pallet that makes remote EVM calls possible.
This bug only existed on Moonbase Alpha during the following runtimes and block ranges:
| Network | Introduced | Fixed | Impacted Block Range |
|:--------------:|:----------:|:------:|:--------------------:|
| Moonbase Alpha | RT1700 | RT1900 | 2529736 - 3069634 |
You can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1790){target=\_blank} for more information.
---
#### Gas Estimation Discrepancy {: #gas-estimation-discrepancy }
There was a difference between estimating the gas for a transaction using a non-transaction call, such as `eth_call`, and the execution of it on-chain. The discrepancy occurred because the non-transactional calls were not properly accounting for `maxFeePerGas` and `maxPriorityFeePerGas`, as such, the ([Proof of Validity](https://wiki.polkadot.com/general/glossary/#proof-of-validity){target=\_blank}) consumed by the Ethereum transaction was counted differently. This was fixed by properly accounting for these fields when estimating the size of the on-chain transaction.
This bug existed during the following runtimes and block ranges:
| Network | Introduced | Fixed | Impacted Block Range |
|:--------------:|:----------:|:------:|:--------------------:|
| Moonbeam | RT1201 | RT2501 | 415946 - 4543267 |
| Moonriver | RT1201 | RT2500 | 1471037 - 5175574 |
| Moonbase Alpha | RT1200 | RT2500 | 1648994 - 5053547 |
You can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1790/){target=\_blank} for more information.
---
#### Incorrect Effective Gas Price In Transaction Receipts {: #incorrect-effective-gas-price }
The `effectiveGasPrice` value returned by `eth_getTransactionReceipt` was different from the on-chain value due to an incorrect calculation of the base fee. Specifically, the transaction receipt's value was computed using the `NextFeeMultiplier` from the block in which the transaction was included rather than the previous block, which is the correct source for computing the base fee.
This bug existed during the following runtimes and block ranges:
| Network | Introduced | Fixed | Impacted Block Range |
|:--------------:|:----------:|:------:|:--------------------:|
| Moonbeam | RT1201 | RT2801 | 415946 - 5899847 |
| Moonriver | RT1201 | RT2801 | 1471037 - 6411588 |
| Moonbase Alpha | RT1200 | RT2801 | 1648994 - 6209638 |
You can review the [relative Frontier PR](https://github.com/polkadot-evm/frontier/pull/1280){target=\_blank} and [Moonbeam PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/2610){target=\_blank} for more information.
---
#### Skipped Ethereum Transaction Traces {: #skipped-ethereum-transaction-traces }
Runtimes with the `evm-tracing` feature enabled introduced additional `ref_time` overhead due to special logic that traces Ethereum transactions (emitting events for each component: gasometer, runtime, EVM) used to fill information for RPC calls like `debug_traceTransaction` and `trace_filter`.
Since the real `ref_time` in production runtimes is smaller, this could cause the block weight limits to be reached when replaying a block in an EVM-tracing runtime, resulting in skipped transaction traces. This was observed in Moonbeam block [9770044](https://moonbeam.subscan.io/block/9770044){target=\_blank}.
The fix consisted of resetting the previously consumed weight before tracing each Ethereum transaction. It's important to note that this issue only affected code under `evm-tracing`, which is not included in any production runtime.
This bug was fixed in the following runtime:
| Network | Fixed | Impacted Block |
|:--------------:|:------:|:--------------:|
| Moonbeam | RT3501 | 9770044 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/3210){target=\_blank}.
---
#### Notify Inactive Collator Fails for Long-Inactive Collators {: #notify-inactive-collator-fails }
The `notifyInactiveCollator` extrinsic, designed to remove collators from the pool if they haven't produced any blocks in the last two rounds, failed for collators who had been inactive for significantly longer than two rounds. The transaction would only succeed within the first few blocks of a new round.
The bug existed during the following runtimes and block ranges:
| Network | Introduced | Fixed | Impacted Block Range |
|:--------------:|:----------:|:------:|:--------------------:|
| Moonbase Alpha | RT2601 | RT3500 | 5474345 – 10750816 |
| Moonriver | RT2602 | RT3501 | 5638536 – 10665393 |
| Moonbeam | RT2602 | RT3501 | 4977160 – 10056989 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/3128){target=\_blank}.
---
## Migrations {: #migrations }
Migrations are necessary when a storage item is changed or added and needs to be populated with data. The migrations listed below have been organized by the impacted pallet(s).
### Author Mapping Pallet {: #author-mapping }
#### Update the Mapping Storage Item {: #update-mapping-storage-item }
This migration updated the now deprecated `Mapping` storage item of the author mapping pallet to use a more secure hasher type. The hasher type was updated to [Blake2_128Concat](https://paritytech.github.io/substrate/master/frame_support/struct.Blake2_128Concat.html){target=\_blank} instead of [Twox64Concat](https://paritytech.github.io/substrate/master/frame_support/struct.Twox64Concat.html){target=\_blank}.
This migration was only applied to Moonriver and Moonbase Alpha and was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonriver | RT800 | 684728 |
| Moonbase Alpha | RT800 | 915684 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/679){target=\_blank}.
---
#### Add Support for VRF Keys {: #add-support-for-vrf-keys }
When VRF key support was introduced, the `MappingWithDeposit` storage item of the author mapping pallet was updated to include a `keys` field to support VRF keys that can be looked up via the Nimbus ID. A migration was applied to update the existing storage items with this new field.
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT1502 | 1107285 |
| Moonriver | RT1502 | 1814458 |
| Moonbase Alpha | RT1502 | 2112058 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1407){target=\_blank}.
---
#### One Nimbus ID per Account ID {: #one-nimbus-id-per-account-id }
A migration was applied to ensure that an account ID can have only one Nimbus ID. The migration accepted the first Nimbus ID owned by a given account and cleared any additional Nimbus IDs associated with the account. For any cleared associations, the bond for the association was returned.
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT1606 | 1326697 |
| Moonriver | RT1605 | 2077599 |
| Moonbase Alpha | RT1603 | 2285347 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1525){target=\_blank}.
---
### Base Fee Pallet {: #base-fee }
#### Set Elasticity Storage Item Value {: #set-elasticity }
This migration sets the `Elasticity` storage item of the base fee pallet to zero, which results in a constant `BaseFeePerGas`.
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT1300 | 524762 |
| Moonriver | RT1300 | 1541735 |
| Moonbase Alpha | RT1300 | 1761128 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1744){target=\_blank}.
---
### Democracy Pallet {: #democracy }
#### Preimage Storage Moved to New Preimage Pallet
A migration was applied, which moved preimages stored in the democracy pallet to a new preimage pallet. This migration on Moonbeam was required as a result of an [upstream change to Polkadot](https://github.com/paritytech/substrate/pull/11649/){target=\_blank}.
There was one preimage that was affected in Moonbeam, which was dropped from the scheduler queue and never executed: `0x14262a42aa6ccb3cae0a169b939ca5b185bc317bb7c449ca1741a0600008d306`. This preimage was [manually removed](https://moonbeam.subscan.io/extrinsic/2693398-8){target=\_blank} by the account that initially submitted the preimage.
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT2000 | 3310369 |
| Moonriver | RT2000 | 3202604 |
| Moonbase Alpha | RT2000 | 2673234 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1962){target=\_blank}.
---
#### Remove Governance V1 Collectives {: #remove-gov-v1-collectives }
A migration was applied to remove the governance V1 collectives, which included the Council and Technical Committee. The governance V1 collectives were replaced with the OpenGov (governance V2) Technical Committee.
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT2801 | 5899847 |
| Moonriver | RT2801 | 6411588 |
| Moonbase Alpha | RT2801 | 6209638 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/2643){target=\_blank}.
A follow-up migration was required to properly clear the storage entries associated with the governance V1 collectives, which was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT2901 | 6197065 |
| Moonriver | RT2901 | 6699589 |
| Moonbase Alpha | RT2901 | 6710531 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/2711){target=\_blank}.
---
#### Remove Governance V1 Democracy Pallet {: #remove-gov-v1-collectives }
A migration was applied to remove the storage associated with the Democracy Pallet used in governance V1. The Democracy Pallet was replaced with the Preimage, Referenda, and Collective Voting OpenGov (governance V2) pallets.
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT2901 | 6197065 |
| Moonriver | RT2901 | 6699589 |
| Moonbase Alpha | RT2901 | 6710531 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/2685){target=\_blank}.
---
### EVM Pallet {: evm-pallet }
#### EVM Contract Metadata
A migration was introduced to automate the manual process of setting EVM contract metadata for contracts deployed more than two years ago that hadn't been interacted with after the introduction of metadata storage item. This migration replaces the need to manually call `createContractMetadata(address)` on these contracts to make them compatible with the current runtime.
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:---------:|:----------------:|:-------------:|
| Moonbeam | RT3200 | 7985204 |
| Moonriver | RT3200 | 8519187 |
---
### Moonbeam Orbiter Pallet {: #moonbeam-orbiter }
#### Remove the Minimum Bond Requirement for Orbiter Collators {: #remove-orbiter-minimum-bond }
A migration was applied to the Moonbeam Orbiter Pallet that sets the bonds of the existing orbiter collators to zero. This change enabled payouts to be even for future orbiter program expansions.
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT2602 | 4977160 |
| Moonriver | RT2602 | 5638536 |
| Moonbase Alpha | RT2601 | 5474345 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/2526){target=\_blank}.
---
### Parachain Staking Pallet {: #parachain-staking }
#### Update Collator State Storage Item {: #update-collator-state-storage-item }
A migration was applied that updated the `Collator` storage item of the parachain staking pallet to the new `Collator2` storage item. This change updated the collator state to include the following items:
- The `nominators` set is a list of all of the nominator (delegator) account IDs without their respective balance bonded
- A new `top_nominators` storage item that returns a list of all of the top nominators ordered by greatest bond amount to least
- A new `bottom_nominators` storage item that returns a list of all of the bottom nominators ordered by least bond amount to greatest
- The `total` storage item was replaced with `total_counted` and `total_backing`. The `total_counted` item returns the sum of the top nominations and the collator's self-bond, whereas the `total_backing` item returns the sum of all of the nominations and the collator's self-bond
This migration was only applied to Moonriver and Moonbase Alpha and was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonriver | RT53 | 9696 |
| Moonbase Alpha | RT52 | 238827 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/505){target=\_blank}.
---
#### Patch Total Staked Amount {: #patch-total-staked-amount }
A migration was applied to the `total` staked amount of the `CollatorState` storage item in the Parachain Staking Pallet due to a potential bug that may have led to an incorrect amount.
This migration was only applied to Moonriver and Moonbase Alpha and was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonriver | RT53 | 9696 |
| Moonbase Alpha | RT52 | 238827 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/502){target=\_blank}.
---
#### Support Delayed Nominator (Delegator) Exits {: #support-delayed-nominator-exits }
The exit queue for handling candidate exits had been updated to include support for delayed nominator (delegator) exits and revocations, which required a migration to update the `ExitQueue` parachain staking pallet storage item to `ExitQueue2`. The `NominatorState` storage item was also migrated to `NominatorState2` to prevent a nominator from performing more nominations when they already have scheduled an exit.
These migrations were only applied to Moonriver and Moonbase Alpha and were executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonriver | RT200 | 259002 |
| Moonbase Alpha | RT200 | 457614 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/610){target=\_blank}.
---
#### Purge Staking Storage Bloat {: #purge-staking-storage-bloat }
A migration was applied to purge staking storage bloat for the `Points` and `AtStake` storage items of the parachain staking pallet that are older than two rounds.
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT1001 | 5165 |
| Moonriver | RT1001 | 1052242 |
| Moonbase Alpha | RT1001 | 1285916 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/970){target=\_blank}.
---
#### Support Manual Exits and DPoS Terminology {: #support-manual-exits-dpos-terminology }
The parachain staking pallet was updated to include manual exits. If a candidate or delegator wanted to decrease or revoke their bond or leave the candidate or delegator pool, they would need to schedule a request first, wait for a delay period to pass, and then manually execute the request. As such, a migration was applied to replace the automatic exit queue, including the `ExitQueue2` storage item, with a manual exits API.
In addition, a change was made to switch from Nominated Proof of Stake (NPoS) to Delegated Proof of Stake (DPoS) terminology; this marked the sweeping change from "nominate" to "delegate". This required the migration of the following parachain staking pallet storage items:
- `CollatorState2` was migrated to `CandidateState`
- `NominatorState2` was migrated to `DelegatorState`
These migrations were executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT1001 | 5165 |
| Moonriver | RT1001 | 1052242 |
| Moonbase Alpha | RT1001 | 1285916 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/810){target=\_blank}.
---
#### Increase Max Delegations per Candidate {: #increase-max-delegations-per-candidate }
A migration was applied to increase the maximum number of delegations per candidate in the parachain staking pallet. It increased the delegations from 100 to 500 on Moonbase Alpha and Moonriver and from 100 to 1000 on Moonbeam.
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT1101 | 171061 |
| Moonriver | RT1101 | 1188000 |
| Moonbase Alpha | RT1100 | 1426319 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1096){target=\_blank}.
---
#### Split Candidate Delegations into Top and Bottom {: #split-candidate-delegations-top-bottom }
This migration splits the deprecated `CandidateState` storage item of the parachain staking pallet into the following three new storage items to avoid unnecessary storage reads:
- `CandidateInfo`
- `TopDelegations`
- `BottomDelegations`
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT1201 | 415946 |
| Moonriver | RT1201 | 1471037 |
| Moonbase Alpha | RT1200 | 1648994 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1117){target=\_blank}.
---
#### Patch Incorrect Total Delegations {: #patch-incorrect-total-delegations }
There was a migration applied to fix the [Incorrect Collator Selection](#incorrect-collator-selection) bug and patch the delegations total for all candidates.
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT1300 | 524762 |
| Moonriver | RT1300 | 1541735 |
| Moonbase Alpha | RT1300 | 1761128 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1291){target=\_blank}.
---
#### Split Delegator State into Delegation Scheduled Requests {: #split-delegator-state }
A migration was applied that moved pending delegator requests from the `DelegatorState` storage item of the parachain staking pallet into a new `DelegationScheduledRequests` storage item.
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT1502 | 1107285 |
| Moonriver | RT1502 | 1814458 |
| Moonbase Alpha | RT1502 | 2112058 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1408){target=\_blank}.
---
#### Replace Staking Reserves with Locks {: #replace-staking-reserves }
A migration was applied that changed users' staking reserved balances to locked balances. The locked balance is the same type as democracy-locked funds, allowing users to use their staked funds to participate in democracy.
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT1701 | 1581457 |
| Moonriver | RT1701 | 2281723 |
| Moonbase Alpha | RT1700 | 2529736 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1604){target=\_blank}.
---
#### Auto-Compounding Support {: #auto-compounding-support }
To support auto-compounding, two migrations were applied to the `AtStake` storage item in the parachain staking pallet:
- `RemovePaidRoundsFromAtStake` - to remove any stale `AtStake` entries relating to already paid-out rounds with candidates that didn't produce any blocks. This migration is a prerequisite for the `MigrateAtStakeAutoCompound` migration
- `MigrateAtStakeAutoCompound` - migrates the snapshots for unpaid rounds for `AtStake` entries
These migrations were executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT1901 | 2317683 |
| Moonriver | RT1901 | 2911863 |
| Moonbase Alpha | RT1900 | 3069635 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1878){target=\_blank}.
---
#### Switch to Block-Based Staking Rounds {: #block-based-staking-rounds }
A migration was applied to switch from time-based staking rounds to fixed block-based rounds.
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT2801 | 5899847 |
| Moonriver | RT2801 | 6411588 |
| Moonbase Alpha | RT2801 | 6209638 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/2690){target=\_blank}.
---
#### Renaming of Parachain Bond Reserve Events {: #renaming-of-parachain-bond-reserve-events }
Prior to Runtime 3300, the `ReservedForParachainBond` event was emitted once per round to indicate parachain bond reserve funding through inflation. In Runtime 3300, this same event was renamed to `InflationDistributed`.
This change took effect at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT3300 | 8381443 |
| Moonriver | RT3300 | 8894417 |
| Moonbase Alpha | RT3300 | 9062316 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/2976){target=\_blank}.
---
### Referenda Pallet {: #referenda-pallet }
#### Refunds for Submission Deposits {: #refunds-for-submission-deposits }
A migration was introduced to support refunds for submission deposits on closed referenda that updated the `ReferendumInfo` type. The following invariants of `ReferendumInfo` were changed so that the second parameter, `Deposit`, is now optional, `Option>`: `Approved`, `Rejected`, `Cancelled`, and `TimedOut`.
This stemmed from an upstream change to the [Substrate](https://github.com/paritytech/substrate/pull/12788){target=\_blank} repository.
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT2302 | 3456477 |
| Moonriver | RT2302 | 4133065 |
| Moonbase Alpha | RT2301 | 4172407 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/2134){target=\_blank}.
---
#### Restore Corrupted Referenda Deposits {: restore-corrupted-referenda-deposits }
A migration was introduced to support restoring referenda deposits affected by corrupted storage values. The issue arose when a migration was applied twice due to a pallet version error, resulting in invalid values and non-refundable submission deposits. As the number of values to correct was finite and small, this migration created a list to update them by hand.
This migration was only applied to Moonbeam and was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------:|:----------------:|:-------------:|
| Moonbeam | RT3100 | 7303601 |
### XCM-Related Pallets {: #xcm-related-pallets }
#### Update Transact Info Storage Item {: #update-transaction-info }
There was a migration applied to the `TransactInfo` storage item of the XCM Transactor Pallet that changed the following items:
- `max_weight` is added to prevent transactors from stalling the queue in the destination chain
- Removes `fee_per_byte`, `metadata_size`, and `base_weight` as these items are not necessary for XCM transactions
- `fee_per_second` replaces `fee_per_weight` to better reflect cases (like Kusama) in which the `fee_per_weight` unit is lower than one
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT1201 | 415946 |
| Moonriver | RT1201 | 1471037 |
| Moonbase Alpha | RT1200 | 1648994 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1114){target=\_blank}.
---
#### Add Support for Kusama Asset Hub (Statemine) Prefix Breaking Change {: #add-support-statemine-prefix }
The following three migrations were added to the asset manager pallet to avoid issues with Kusama Asset Hub's (previously referred to as Statemine) [breaking change to the way it represents assets](https://github.com/paritytech/cumulus/pull/831){target=\_blank} and possible future breaking changes:
- `UnitsWithAssetType` - updates the `AssetTypeUnitsPerSecond` storage item to a mapping of the `AssetType` to `units_per_second`, instead of the mapping `AssetId` to `units_per_second`. This is done to avoid additional migrations whenever a breaking change arises
- `PopulateAssetTypeIdStorage` - creates a new `AssetTypeId` storage item that holds the `AssetType` to `AssetId` mapping, which allows the decoupling of `assetIds` and `AssetTypes`
- `ChangeStateminePrefixes` - updates already registered Kusama Asset Hub (Statemine) assets to their new form
These migrations were executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT1201 | 415946 |
| Moonriver | RT1201 | 1471037 |
| Moonbase Alpha | RT1200 | 1648994 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1159){target=\_blank}.
---
#### Add New Supported Fee Payment Assets Storage Item {: #add-supported-fee-payment-assets }
A migration was applied to the asset manager pallet, creating a new `SupportedFeePaymentAssets` storage item by reading the supported asset data from the `AssetTypeUnitsPerSecond` storage item. This storage item will hold all the assets we accept for XCM fee payment. It will be read when an incoming XCM message is received, and if the asset is not in storage, the message will not be processed.
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT1300 | 524762 |
| Moonriver | RT1300 | 1541735 |
| Moonbase Alpha | RT1300 | 1761128 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1118){target=\_blank}.
---
#### Update the XCM Transactor Storage from V2 to V3 {: #update-xcm-transactor }
With the support of XCM V3, a migration was applied to update the XCM Transactor pallet's storage from XCM V2 to V3. The `transactInfoWithWeightLimit` and `destinationAssetFeePerSecond` storage items were updated to support XCM V3 multilocations.
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT2302 | 3456477 |
| Moonriver | RT2302 | 4133065 |
| Moonbase Alpha | RT2301 | 4172407 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/2145){target=\_blank}.
---
#### Remove Mintable XC-20s {: #remove-local-assets }
Mintable XC-20s were deprecated in favor of XCM-enabled ERC-20s; as such, a migration was applied to remove the local assets pallet and clear the assets in storage.
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT2801 | 5899847 |
| Moonriver | RT2801 | 6411588 |
| Moonbase Alpha | RT2801 | 6209638 |
For more information, you can review the [relative PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/2634){target=\_blank}.
---
#### Manage Foreign Assets via Smart Contracts {: #foreign-assets-migration }
A migration was applied to transition existing foreign assets to a new design that manages XCM derivative assets on Moonbeam through EVM smart contracts instead of the previous implementation using the Asset and Asset Manager pallets. The migration process involved several extrinsics in the Moonbeam Lazy Migration pallet:
- **`approve_assets_to_migrate`** - sets the list of asset IDs approved for migration
- **`start_foreign_asset_migration`** - initiates migration for a specific foreign asset by freezing the original asset and creating a new EVM smart contract
- **`migrate_foreign_asset_balances`** - migrates asset balances in batches from old assets pallet to the new system
- **`migrate_foreign_asset_approvals`** - migrates asset approvals in batches while unreserving deposits from the old approval system
- **`finish_foreign_asset_migration`** - completes migration after all balances and approvals are migrated and performs final cleanup
This migration preserves compatibility with existing foreign assets by identifying each foreign asset with the same AssetID integer as before. This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT3501 | 10056989 |
| Moonriver | RT3501 | 10665393 |
| Moonbase Alpha | RT3500 | 10750816 |
For more information, you can review the relative PRs on GitHub: [2869](https://github.com/moonbeam-foundation/moonbeam/pull/2869){target=\_blank} and [3020](https://github.com/moonbeam-foundation/moonbeam/pull/3020){target=\_blank}.
---
### Nimbus Author Filter Pallet {: #nimbus }
#### Replace Eligible Ratio with Eligible Count {: #replace-eligible-ratio }
A breaking change was applied to the Nimbus repository, deprecating `EligibleRatio` in favor of the `EligibleCount` config. As a result, a migration was applied to the Moonbeam repository, populating the new `EligibleCount` value as a percentage of the potential authors defined at that block height if the `EligibleRatio` value existed. Otherwise, the value was set to a default value of `50`.
This migration was executed at the following runtimes and blocks:
| Network | Executed Runtime | Block Applied |
|:--------------:|:----------------:|:-------------:|
| Moonbeam | RT1502 | 1107285 |
| Moonriver | RT1502 | 1814458 |
| Moonbase Alpha | RT1502 | 2112058 |
For more information, you can review the [relative Nimbus PR](https://github.com/moonbeam-foundation/nimbus/pull/45){target=\_blank} and [Moonbeam PR on GitHub](https://github.com/moonbeam-foundation/moonbeam/pull/1400){target=\_blank}.
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/build/runtime-upgrades/
--- BEGIN CONTENT ---
---
title: Runtime Upgrades
description: A historical record of each runtime upgrade and the block at which the runtime was executed for Moonbeam, Moonriver, and the Moonbase Alpha TestNet.
categories: Reference
---
# Runtime Upgrades
## Introduction {: #introduction }
Moonbeam runtime upgrades allow for the maintenance and evolution of the chain logic without the need for a hard fork. These runtime upgrades can introduce new features, improve performance, fix bugs, and respond to changing requirements.
This page provides a historical record of runtime upgrades by block for each of the Moonbeam-based networks.
## Runtime Upgrades by Block {: #runtime-upgrades-by-block }
The following table contains a list of the runtime upgrades and the block at which the upgrade occurred for each network. Runtime upgrades occur first on Moonbase Alpha before being released on Moonriver and then on Moonbeam. You can read the release notes for each runtime on the [Moonbeam releases GitHub page](https://github.com/moonbeam-foundation/moonbeam/releases){target=\_blank}.
Not all runtime upgrades are released on each network, as sometimes after releasing the initial runtime upgrade, the need for a subsequent upgrade arises. If a runtime upgrade version has been skipped or hasn't been released yet (only applicable to the latest runtime upgrade), you'll see a `-` in that row.
| Runtime | Moonbeam | Moonriver | Moonbase Alpha |
|:----------------------------------------------------------------------------------------:|:----------------------------------------------------------------------:|:-----------------------------------------------------------------------:|:----------------------------------------------------------------------:|
| 40 | - | - | [0](https://moonbase.subscan.io/block/0){target=\_blank} |
| 44 | - | - | [142863](https://moonbase.subscan.io/block/142863){target=\_blank} |
| 47 | - | - | [209144](https://moonbase.subscan.io/block/209144){target=\_blank} |
| 49 | - | [0](https://moonriver.subscan.io/block/0){target=\_blank} | - |
| 52 | - | - | [238827](https://moonbase.subscan.io/block/238827){target=\_blank} |
| 53 | - | [9696](https://moonriver.subscan.io/block/9696){target=\_blank} | - |
| 155 | - | [67938](https://moonriver.subscan.io/block/67938){target=\_blank} | [278703](https://moonbase.subscan.io/block/278703){target=\_blank} |
| 159 | - | [166749](https://moonriver.subscan.io/block/166749){target=\_blank} | [383465](https://moonbase.subscan.io/block/383465){target=\_blank} |
| 200 | - | [259002](https://moonriver.subscan.io/block/259002){target=\_blank} | [457614](https://moonbase.subscan.io/block/457614){target=\_blank} |
| 300 | - | [344698](https://moonriver.subscan.io/block/344698){target=\_blank} | [485543](https://moonbase.subscan.io/block/485543){target=\_blank} |
| 400 | - | [400458](https://moonriver.subscan.io/block/400458){target=\_blank} | [610935](https://moonbase.subscan.io/block/610935){target=\_blank} |
| 501 | - | [430442](https://moonriver.subscan.io/block/430442){target=\_blank} | [653692](https://moonbase.subscan.io/block/653692){target=\_blank} |
| 600 | - | [455107](https://moonriver.subscan.io/block/455107){target=\_blank} | [675176](https://moonbase.subscan.io/block/675176){target=\_blank} |
| 701 | - | [581187](https://moonriver.subscan.io/block/581187){target=\_blank} | [797200](https://moonbase.subscan.io/block/797200){target=\_blank} |
| 800 | - | [684728](https://moonriver.subscan.io/block/684728){target=\_blank} | [915684](https://moonbase.subscan.io/block/915684){target=\_blank} |
| 900 | [0](https://moonbeam.subscan.io/block/0){target=\_blank} | [923864](https://moonriver.subscan.io/block/923864){target=\_blank} | [1075626](https://moonbase.subscan.io/block/1075626){target=\_blank} |
| 901 | - | - | [1130271](https://moonbase.subscan.io/block/1130271){target=\_blank} |
| 902 | - | - | [1175311](https://moonbase.subscan.io/block/1175311){target=\_blank} |
| 1001 | [5165](https://moonbeam.subscan.io/block/5165){target=\_blank} | [1052242](https://moonriver.subscan.io/block/1052242){target=\_blank} | [1285916](https://moonbase.subscan.io/block/1285916){target=\_blank} |
| 1002 | [32532](https://moonbeam.subscan.io/block/32532){target=\_blank} | [1141593](https://moonriver.subscan.io/block/1141593){target=\_blank} | [1396972](https://moonbase.subscan.io/block/1396972){target=\_blank} |
| 1101 | [171061](https://moonbeam.subscan.io/block/171061){target=\_blank} | [1188000](https://moonriver.subscan.io/block/1188000){target=\_blank} | [1426319](https://moonbase.subscan.io/block/1426319){target=\_blank} |
| 1102 | [214641](https://moonbeam.subscan.io/block/214641){target=\_blank} | [1295420](https://moonriver.subscan.io/block/1295420){target=\_blank} | [1517440](https://moonbase.subscan.io/block/1517440){target=\_blank} |
| 1103 | [312036](https://moonbeam.subscan.io/block/312036){target=\_blank} | [1389122](https://moonriver.subscan.io/block/1389122){target=\_blank} | [1591913](https://moonbase.subscan.io/block/1591913){target=\_blank} |
| 1200 | - | - | [1648994](https://moonbase.subscan.io/block/1648994){target=\_blank} |
| 1201 | [415946](https://moonbeam.subscan.io/block/415946){target=\_blank} | [1471037](https://moonriver.subscan.io/block/1471037){target=\_blank} | [1679619](https://moonbase.subscan.io/block/1679619){target=\_blank} |
| 1300 | [524762](https://moonbeam.subscan.io/block/524762){target=\_blank} | [1541735](https://moonriver.subscan.io/block/1541735){target=\_blank} | [1761128](https://moonbase.subscan.io/block/1761128){target=\_blank} |
| 1400 | - | - | [1962557](https://moonbase.subscan.io/block/1962557){target=\_blank} |
| 1401 | [915320](https://moonbeam.subscan.io/block/915320){target=\_blank} | [1705939](https://moonriver.subscan.io/block/1705939){target=\_blank} | [1967358](https://moonbase.subscan.io/block/1967358){target=\_blank} |
| 1502 | [1107285](https://moonbeam.subscan.io/block/1107285){target=\_blank} | [1814458](https://moonriver.subscan.io/block/1814458){target=\_blank} | [2112058](https://moonbase.subscan.io/block/2112058){target=\_blank} |
| 1503 | [1115896](https://moonbeam.subscan.io/block/1115896){target=\_blank} | [1909326](https://moonriver.subscan.io/block/1909326){target=\_blank} | [2220736](https://moonbase.subscan.io/block/2220736){target=\_blank} |
| 1504 | [1117310](https://moonbeam.subscan.io/block/1117310){target=\_blank} | [1910640](https://moonriver.subscan.io/block/1910640){target=\_blank} | [2221773](https://moonbase.subscan.io/block/2221773){target=\_blank} |
| 1603 | - | - | [2285347](https://moonbase.subscan.io/block/2285347){target=\_blank} |
| 1605 | - | [2077599](https://moonriver.subscan.io/block/2077599){target=\_blank} | [2318567](https://moonbase.subscan.io/block/2318567){target=\_blank} |
| 1606 | [1326697](https://moonbeam.subscan.io/block/1326697){target=\_blank} | [2105127](https://moonriver.subscan.io/block/2105127){target=\_blank} | [2379759](https://moonbase.subscan.io/block/2379759){target=\_blank} |
| 1700 | - | - | [2529736](https://moonbase.subscan.io/block/2529736){target=\_blank} |
| 1701 | [1581457](https://moonbeam.subscan.io/block/1581457){target=\_blank} | [2281723](https://moonriver.subscan.io/block/2281723){target=\_blank} | [2534200](https://moonbase.subscan.io/block/2534200){target=\_blank} |
| 1702 | [1821212](https://moonbeam.subscan.io/block/1821212){target=\_blank} | [2524247](https://moonriver.subscan.io/block/2524247){target=\_blank} | - |
| 1800 | - | - | [2748786](https://moonbase.subscan.io/block/2748786){target=\_blank} |
| 1801 | - | [2572556](https://moonriver.subscan.io/block/2572556){target=\_blank} | [2830542](https://moonbase.subscan.io/block/2830542){target=\_blank} |
| 1802 | [1919458](https://moonbeam.subscan.io/block/1919458){target=\_blank} | [2616190](https://moonriver.subscan.io/block/2616190){target=\_blank} | [2879403](https://moonbase.subscan.io/block/2879403){target=\_blank} |
| 1803 | [2073477](https://moonbeam.subscan.io/block/2073477){target=\_blank} | [2767174](https://moonriver.subscan.io/block/2767174){target=\_blank} | [3004714](https://moonbase.subscan.io/block/3004714){target=\_blank} |
| 1900 | - | - | [3069635](https://moonbase.subscan.io/block/3069635){target=\_blank} |
| 1901 | [2317683](https://moonbeam.subscan.io/block/2317683){target=\_blank} | [2911863](https://moonriver.subscan.io/block/2911863){target=\_blank} | [3073562](https://moonbase.subscan.io/block/3073562){target=\_blank} |
| 2000 | [2673234](https://moonbeam.subscan.io/block/2673234){target=\_blank} | [3202604](https://moonriver.subscan.io/block/3202604){target=\_blank} | [3310369](https://moonbase.subscan.io/block/3310369){target=\_blank} |
| 2100 | [3011798](https://moonbeam.subscan.io/block/3011798){target=\_blank} | [3588831](https://moonriver.subscan.io/block/3588831){target=\_blank} | [3609708](https://moonbase.subscan.io/block/3609708){target=\_blank} |
| 2201 | [3290853](https://moonbeam.subscan.io/block/3290853){target=\_blank} | [3858885](https://moonriver.subscan.io/block/3858885){target=\_blank} | [3842850](https://moonbase.subscan.io/block/3842850){target=\_blank} |
| 2301 | - | - | [4172407](https://moonbase.subscan.io/block/4172407){target=\_blank} |
| 2302 | [3456477](https://moonbeam.subscan.io/block/3456477){target=\_blank} | [4133065](https://moonriver.subscan.io/block/4133065){target=\_blank} | [4193323](https://moonbase.subscan.io/block/4193323){target=\_blank} |
| 2401 | - | [4668844](https://moonriver.subscan.io/block/4668844){target=\_blank} | [4591616](https://moonbase.subscan.io/block/4591616){target=\_blank} |
| 2402 | - | - | [4772817](https://moonbase.subscan.io/block/4772817){target=\_blank} |
| 2403 | [4163078](https://moonbeam.subscan.io/block/4163078){target=\_blank} | [4770488](https://moonriver.subscan.io/block/4770488){target=\_blank} | [4804425](https://moonbase.subscan.io/block/4804425){target=\_blank} |
| 2500 | - | [5175574](https://moonriver.subscan.io/block/5175574){target=\_blank} | [5053547](https://moonbase.subscan.io/block/5053547){target=\_blank} |
| 2501 | [4543267](https://moonbeam.subscan.io/block/4543267){target=\_blank} | [5211264](https://moonriver.subscan.io/block/5211264){target=\_blank} | [5194594](https://moonbase.subscan.io/block/5194594){target=\_blank} |
| [2601](https://forum.moonbeam.network/t/runtime-rt2600-schedule/1372/5){target=\_blank} | - | - | [5474345](https://moonbase.subscan.io/block/5474345){target=\_blank} |
| [2602](https://forum.moonbeam.network/t/runtime-rt2600-schedule/1372/13){target=\_blank} | [4977160](https://moonbeam.subscan.io/block/4977160){target=\_blank} | [5638536](https://moonriver.subscan.io/block/5638536){target=\_blank} | [5576588](https://moonbase.subscan.io/block/5576588){target=\_blank} |
| [2700](https://forum.moonbeam.network/t/runtime-rt2700-schedule/1441/3){target=\_blank} | [5504531](https://moonbeam.subscan.io/block/5504531){target=\_blank} | [6041969](https://moonriver.subscan.io/block/6041969){target=\_blank} | [5860584](https://moonbase.subscan.io/block/5860584){target=\_blank} |
| [2801](https://forum.moonbeam.network/t/runtime-rt2801-schedule/1616/4){target=\_blank} | [5899847](https://moonbeam.subscan.io/block/5899847){target=\_blank} | [6411588](https://moonriver.subscan.io/block/6411588){target=\_blank} | [6209638](https://moonbase.subscan.io/block/6209638){target=\_blank} |
| [2901](https://forum.moonbeam.network/t/runtime-rt2901-schedule/1695/3){target=\_blank} | [6197065](https://moonbeam.subscan.io/block/6197065){target=\_blank} | [6699589](https://moonriver.subscan.io/block/6699589){target=\_blank} | [6710531](https://moonbase.subscan.io/block/6710531){target=\_blank} |
| 2902 | - | - | [6732678](https://moonbase.subscan.io/block/6732678){target=\_blank} |
| [3000](https://forum.moonbeam.network/t/runtime-rt3000-schedule/1752/2){target=\_blank} | - | [7043011](https://moonriver.subscan.io/block/7043011){target=\_blank} | [7299818](https://moonbase.subscan.io/block/7299818){target=\_blank} |
| 3001 | [6593037](https://moonbeam.subscan.io/block/6593037){target=\_blank} | - | - |
| [3100](https://forum.moonbeam.network/t/runtime-rt3100-schedule/1801){target=\_blank} | [7303601](https://moonbeam.subscan.io/block/7303601){target=\_blank} | [7829527](https://moonriver.subscan.io/block/7829527){target=\_blank} | [8034666](https://moonbase.subscan.io/block/8034666){target=\_blank} |
| [3102](https://forum.moonbeam.network/t/runtime-rt3100-schedule/1801/10){target=\_blank} | [7586782](https://moonbeam.subscan.io/block/7586782){target=\_blank} | - | - |
| [3200](https://forum.moonbeam.network/t/runtime-rt3200-schedule/1881){target=\_blank} | [7985204](https://moonbeam.subscan.io/block/7985204){target=\_blank} | [8519187](https://moonriver.subscan.io/block/8519187){target=\_blank} | [8722328](https://moonbase.subscan.io/block/8722328){target=\_blank} |
| [3300](https://forum.moonbeam.network/t/runtime-rt3300-schedule/1897){target=\_blank} | [8381443](https://moonbeam.subscan.io/block/8381443){target=\_blank} | [8894417](https://moonriver.subscan.io/block/8894417){target=\_blank} | [9062316](https://moonbase.subscan.io/block/9062316){target=\_blank} |
| [3400](https://forum.moonbeam.network/t/runtime-rt3400-schedule/1954){target=\_blank} | [9376921](https://moonbeam.subscan.io/block/9376921){target=\_blank} | [9774989](https://moonriver.subscan.io/block/9774989){target=\_blank} | [9830392](https://moonbase.subscan.io/block/9830392){target=\_blank} |
| [3401](https://forum.moonbeam.network/t/runtime-rt3400-schedule/1954/6){target=\_blank} | [9661355](https://moonbeam.subscan.io/block/9661355){target=\_blank} | [10269872](https://moonriver.subscan.io/block/10269872){target=\_blank} | [10422450](https://moonbase.subscan.io/block/10422450){target=\_blank} |
| [3500](https://forum.moonbeam.network/t/runtime-rt3501-schedule/2010){target=\_blank} | - | - | [10750816](https://moonbase.subscan.io/block/10750816){target=\_blank} |
| [3501](https://forum.moonbeam.network/t/runtime-rt3501-schedule/2010){target=\_blank} | [10056989](https://moonbeam.subscan.io/block/10056989){target=\_blank} | [10665393](https://moonriver.subscan.io/block/10665393){target=\_blank} | [10833906](https://moonbase.subscan.io/block/10833906){target=\_blank} |
| [3600](https://forum.moonbeam.network/t/runtime-rt3600-schedule/2071){target=\_blank} | [10746745](https://moonbeam.subscan.io/block/10746745){target=\_blank} | [11251274](https://moonriver.subscan.io/block/11251274){target=\_blank} | [11452321](https://moonbase.subscan.io/block/11452321){target=\_blank} |
| [3601](https://forum.moonbeam.network/t/proposals-mr77-mb110-whitelisted-authorize-upgrade-to-rt3601-on-moonriver-and-moonbeam/2139){target=\_blank} | [10999397](https://moonbeam.subscan.io/block/10999397){target=\_blank} | [11692212](https://moonriver.subscan.io/block/11692212){target=\_blank} | - |
| [3700](https://forum.moonbeam.network/t/runtime-rt3700-schedule/2129){target=\_blank} | - | - | [12152458](https://moonbase.subscan.io/block/12152458){target=\_blank} |
| [3701](https://forum.moonbeam.network/t/runtime-rt3700-schedule/2129){target=\_blank} | [11426910](https://moonbeam.subscan.io/block/11426910) | [12003279](https://moonriver.subscan.io/block/12003279){target=\_blank} | [12242104](https://moonbase.subscan.io/block/12242104){target=\_blank} |
| [3702](https://forum.moonbeam.network/t/proposals-mr81-mb118-authorize-upgrade-to-rt3702-on-moonriver-and-moonbeam-via-whitelist/2173){target=\_blank} | [11499659](https://moonbeam.subscan.io/block/11499659){target=\_blank} | [12156948](https://moonriver.subscan.io/block/12156948){target=\_blank} | [12683255](https://moonbase.subscan.io/block/12683255){target=\_blank} |
| [3800](https://forum.moonbeam.network/t/runtime-rt3800-schedule/2188){target=\_blank} | [12120762](https://moonbeam.subscan.io/block/12120762){target=\_blank} | [12540836](https://moonriver.subscan.io/block/12540836){target=\_blank} | [12853655](https://moonbase.subscan.io/block/12853655){target=\_blank} |
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/ethereum/canonical-contracts/
--- BEGIN CONTENT ---
---
title: Canonical Contract Addresses on Moonbeam
description: Overview of the canonical contracts available on Moonbeam, Moonriver, & Moonbase Alpha, including common-good contracts and precompiles.
keywords: canonical, ethereum, moonbeam, precompiled, contracts
categories: Reference, Precompiles, Ethereum Toolkit
---
# Canonical Contracts
## Common-good Contracts {: #common-goods-contracts }
The following contracts addresses have been established:
=== "Moonbeam"
| Contract | Address |
|:------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [WGLMR](https://moonbeam.moonscan.io/address/0xAcc15dC74880C9944775448304B263D191c6077F#code){target=\_blank} | 0xAcc15dC74880C9944775448304B263D191c6077F |
| [Multicall](https://moonbeam.moonscan.io/address/0x83e3b61886770de2F64AAcaD2724ED4f08F7f36B#code){target=\_blank} | 0x83e3b61886770de2F64AAcaD2724ED4f08F7f36B |
| [Multicall2](https://moonbeam.moonscan.io/address/0x6477204E12A7236b9619385ea453F370aD897bb2#code){target=\_blank} | 0x6477204E12A7236b9619385ea453F370aD897bb2 |
| [Multicall3](https://moonbeam.moonscan.io/address/0xca11bde05977b3631167028862be2a173976ca11#code){target=\_blank} | 0xcA11bde05977b3631167028862bE2a173976CA11 |
| [Multisig Factory](https://moonbeam.moonscan.io/address/0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2#code){target=\_blank} | 0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2 |
| [EIP-1820](https://eips.ethereum.org/EIPS/eip-1820){target=\_blank} | 0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24 |
=== "Moonriver"
| Contract | Address |
|:-------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [WMOVR](https://moonriver.moonscan.io/token/0x98878b06940ae243284ca214f92bb71a2b032b8a#code){target=\_blank} | 0x98878B06940aE243284CA214f92Bb71a2b032B8A |
| [Multicall](https://moonriver.moonscan.io/address/0x30f283Cc0284482e9c29dFB143bd483B5C19954b#code){target=\_blank}* | 0x30f283Cc0284482e9c29dFB143bd483B5C19954b |
| [Multicall2](https://moonriver.moonscan.io/address/0xaef00a0cf402d9dedd54092d9ca179be6f9e5ce3#code){target=\_blank} | 0xaef00a0cf402d9dedd54092d9ca179be6f9e5ce3 |
| [Multicall3](https://moonriver.moonscan.io/address/0xca11bde05977b3631167028862be2a173976ca11#code){target=\_blank} | 0xcA11bde05977b3631167028862bE2a173976CA11 |
| [Multisig Factory](https://moonriver.moonscan.io/address/0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2#code){target=\_blank} | 0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2 |
| [EIP-1820](https://eips.ethereum.org/EIPS/eip-1820){target=\_blank} | 0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24 |
_*Deployed by SushiSwap_
=== "Moonbase Alpha"
| Contract | Address |
|:------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [WDEV](https://moonbase.moonscan.io/address/0xD909178CC99d318e4D46e7E66a972955859670E1#code){target=\_blank} | 0xD909178CC99d318e4D46e7E66a972955859670E1 |
| [Multicall](https://moonbase.moonscan.io/address/0x4E2cfca20580747AdBA58cd677A998f8B261Fc21#code){target=\_blank}* | 0x4E2cfca20580747AdBA58cd677A998f8B261Fc21 |
| [Multicall2](https://moonbase.moonscan.io/address/0x37084d0158C68128d6Bc3E5db537Be996f7B6979#code){target=\_blank} | 0x37084d0158C68128d6Bc3E5db537Be996f7B6979 |
| [Multicall3](https://moonbase.moonscan.io/address/0xca11bde05977b3631167028862be2a173976ca11#code){target=\_blank} | 0xcA11bde05977b3631167028862bE2a173976CA11 |
| [Multisig Factory](https://moonbase.moonscan.io/address/0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2#code){target=\_blank} | 0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2 |
| [EIP-1820](https://eips.ethereum.org/EIPS/eip-1820){target=\_blank} | 0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24 |
_*Deployed in the [UniswapV2 Demo Repo](https://github.com/papermoonio/moonbeam-uniswap/tree/main/uniswap-contracts-moonbeam){target=\_blank}_
## Precompiled Contracts {: #precompiled-contracts }
There are a set of precompiled contracts included on Moonbeam, Moonriver, and Moonbase Alpha that are categorized by address and based on the origin network. If you were to convert the precompiled addresses to decimal format, and break them into categories by numeric value, the categories are as follows:
- **0-1023** - [Ethereum MainNet precompiles](#ethereum-mainnet-precompiles)
- **1024-2047** - precompiles that are [not in Ethereum and not Moonbeam specific](#non-moonbeam-specific-nor-ethereum-precomiles)
- **2048-4095** - [Moonbeam specific precompiles](#moonbeam-specific-precompiles)
### Ethereum MainNet Precompiles {: #ethereum-mainnet-precompiles }
=== "Moonbeam"
| Contract | Address |
|:---------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [ECRECOVER](/builders/ethereum/precompiles/utility/eth-mainnet/#verify-signatures-with-ecrecover){target=\_blank} | 0x0000000000000000000000000000000000000001 |
| [SHA256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha256){target=\_blank} | 0x0000000000000000000000000000000000000002 |
| [RIPEMD160](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-ripemd-160){target=\_blank} | 0x0000000000000000000000000000000000000003 |
| [Identity](/builders/ethereum/precompiles/utility/eth-mainnet/#the-identity-function){target=\_blank} | 0x0000000000000000000000000000000000000004 |
| [Modular Exponentiation](/builders/ethereum/precompiles/utility/eth-mainnet/#modular-exponentiation){target=\_blank} | 0x0000000000000000000000000000000000000005 |
| [BN128Add](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128add){target=\_blank} | 0x0000000000000000000000000000000000000006 |
| [BN128Mul](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128mul){target=\_blank} | 0x0000000000000000000000000000000000000007 |
| [BN128Pairing](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128pairing){target=\_blank} | 0x0000000000000000000000000000000000000008 |
| [Blake2](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_blake2/struct.Blake2F.html){target=\_blank} | 0x0000000000000000000000000000000000000009 |
| [P256Verify](https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md){target=\_blank} | 0x0000000000000000000000000000000000000100 |
=== "Moonriver"
| Contract | Address |
|:---------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [ECRECOVER](/builders/ethereum/precompiles/utility/eth-mainnet/#verify-signatures-with-ecrecover){target=\_blank} | 0x0000000000000000000000000000000000000001 |
| [SHA256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha256){target=\_blank} | 0x0000000000000000000000000000000000000002 |
| [RIPEMD160](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-ripemd-160){target=\_blank} | 0x0000000000000000000000000000000000000003 |
| [Identity](/builders/ethereum/precompiles/utility/eth-mainnet/#the-identity-function){target=\_blank} | 0x0000000000000000000000000000000000000004 |
| [Modular Exponentiation](/builders/ethereum/precompiles/utility/eth-mainnet/#modular-exponentiation){target=\_blank} | 0x0000000000000000000000000000000000000005 |
| [BN128Add](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128add){target=\_blank} | 0x0000000000000000000000000000000000000006 |
| [BN128Mul](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128mul){target=\_blank} | 0x0000000000000000000000000000000000000007 |
| [BN128Pairing](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128pairing){target=\_blank} | 0x0000000000000000000000000000000000000008 |
| [Blake2](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_blake2/struct.Blake2F.html){target=\_blank} | 0x0000000000000000000000000000000000000009 |
| [P256Verify](https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md){target=\_blank} | 0x0000000000000000000000000000000000000100 |
=== "Moonbase Alpha"
| Contract | Address |
|:---------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [ECRECOVER](/builders/ethereum/precompiles/utility/eth-mainnet/#verify-signatures-with-ecrecover){target=\_blank} | 0x0000000000000000000000000000000000000001 |
| [SHA256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha256){target=\_blank} | 0x0000000000000000000000000000000000000002 |
| [RIPEMD160](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-ripemd-160){target=\_blank} | 0x0000000000000000000000000000000000000003 |
| [Identity](/builders/ethereum/precompiles/utility/eth-mainnet/#the-identity-function){target=\_blank} | 0x0000000000000000000000000000000000000004 |
| [Modular Exponentiation](/builders/ethereum/precompiles/utility/eth-mainnet/#modular-exponentiation){target=\_blank} | 0x0000000000000000000000000000000000000005 |
| [BN128Add](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128add){target=\_blank} | 0x0000000000000000000000000000000000000006 |
| [BN128Mul](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128mul){target=\_blank} | 0x0000000000000000000000000000000000000007 |
| [BN128Pairing](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128pairing){target=\_blank} | 0x0000000000000000000000000000000000000008 |
| [Blake2](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_blake2/struct.Blake2F.html){target=\_blank} | 0x0000000000000000000000000000000000000009 |
| [P256Verify](https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md){target=\_blank} | 0x0000000000000000000000000000000000000100 |
### Non-Moonbeam Specific nor Ethereum Precompiles {: #non-moonbeam-specific-nor-ethereum-precompiles }
=== "Moonbeam"
| Contract | Address |
|:--------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [SHA3FIPS256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha3fips256){target=\_blank} | 0x0000000000000000000000000000000000000400 |
| Dispatch [Removed] | 0x0000000000000000000000000000000000000401 |
| [ECRecoverPublicKey](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_simple/struct.ECRecoverPublicKey.html){target=\_blank} | 0x0000000000000000000000000000000000000402 |
=== "Moonriver"
| Contract | Address |
|:--------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [SHA3FIPS256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha3fips256){target=\_blank} | 0x0000000000000000000000000000000000000400 |
| Dispatch [Removed] | 0x0000000000000000000000000000000000000401 |
| [ECRecoverPublicKey](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_simple/struct.ECRecoverPublicKey.html){target=\_blank} | 0x0000000000000000000000000000000000000402 |
=== "Moonbase Alpha"
| Contract | Address |
|:-------------------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [SHA3FIPS256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha3fips256){target=\_blank} | 0x0000000000000000000000000000000000000400 |
| Dispatch [Removed] | 0x0000000000000000000000000000000000000401 |
| [ECRecoverPublicKey](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_simple/struct.ECRecoverPublicKey.html){target=\_blank} | 0x0000000000000000000000000000000000000402 |
### Moonbeam-Specific Precompiles {: #moonbeam-specific-precompiles }
=== "Moonbeam"
| Contract | Address |
|:-------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------:|
| [Parachain Staking](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/parachain-staking/StakingInterface.sol){target=\_blank} | {{networks.moonbeam.precompiles.staking}} |
| [Crowdloan Rewards](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/crowdloan-rewards/CrowdloanInterface.sol){target=\_blank} | {{networks.moonbeam.precompiles.crowdloan}} |
| [ERC-20 Interface](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/balances-erc20/ERC20.sol){target=\_blank} | {{networks.moonbeam.precompiles.erc20}} |
| Democracy [Removed] | {{networks.moonbeam.precompiles.democracy}} |
| [X-Tokens](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xtokens/Xtokens.sol){target=\_blank} | {{networks.moonbeam.precompiles.xtokens}} |
| [Relay Encoder](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/relay-encoder/RelayEncoder.sol){target=\_blank} | {{networks.moonbeam.precompiles.relay_encoder}} |
| [XCM Transactor V1](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v1/XcmTransactorV1.sol){target=\_blank} | {{networks.moonbeam.precompiles.xcm_transactor_v1}} |
| [Author Mapping](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/author-mapping/AuthorMappingInterface.sol){target=\_blank} | {{networks.moonbeam.precompiles.author_mapping}} |
| [Batch](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/batch/Batch.sol){target=\_blank} | {{networks.moonbeam.precompiles.batch}} |
| [Randomness](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/randomness/Randomness.sol){target=\_blank} | {{networks.moonbeam.precompiles.randomness}} |
| [Call Permit](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/call-permit/CallPermit.sol){target=\_blank} | {{networks.moonbeam.precompiles.call_permit}} |
| [Proxy](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/proxy/Proxy.sol){target=\_blank} | {{networks.moonbeam.precompiles.proxy}} |
| [XCM Utilities](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-utils/XcmUtils.sol){target=\_blank} | {{networks.moonbeam.precompiles.xcm_utils}} |
| [XCM Transactor V2](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v2/XcmTransactorV2.sol){target=\_blank} | {{networks.moonbeam.precompiles.xcm_transactor_v2}} |
| [Council Collective [Removed]](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbeam.precompiles.collective_council}} |
| [Technical Committee Collective [Removed]](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbeam.precompiles.collective_tech_committee}} |
| [Treasury Council Collective](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbeam.precompiles.collective_treasury}} |
| [Referenda](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/referenda/Referenda.sol){target=\_blank} | {{networks.moonbeam.precompiles.referenda}} |
| [Conviction Voting](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/conviction-voting/ConvictionVoting.sol){target=\_blank} | {{networks.moonbeam.precompiles.conviction_voting}} |
| [Preimage](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/preimage/Preimage.sol){target=\_blank} | {{networks.moonbeam.precompiles.preimage}} |
| [OpenGov Tech Committee](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbeam.precompiles.collective_opengov_tech_committee}} |
| [Precompile Registry](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/precompile-registry/PrecompileRegistry.sol){target=\_blank} | {{networks.moonbeam.precompiles.registry}} |
| [GMP](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/gmp/Gmp.sol){target=\_blank} | {{networks.moonbeam.precompiles.gmp}} |
| [XCM Transactor V3](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v3/XcmTransactorV3.sol){target=\_blank} | {{networks.moonbeam.precompiles.xcm_transactor_v3}} |
| [Identity](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/identity/Identity.sol){target=\_blank} | {{networks.moonbeam.precompiles.identity}} |
| [XCM Interface](https://github.com/Moonsong-Labs/moonkit/blob/main/precompiles/pallet-xcm/XcmInterface.sol){target=\_blank} | {{networks.moonbeam.precompiles.xcm_interface}} |
=== "Moonriver"
| Contract | Address |
|:-------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------:|
| [Parachain Staking](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/parachain-staking/StakingInterface.sol){target=\_blank} | {{networks.moonriver.precompiles.staking}} |
| [Crowdloan Rewards](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/crowdloan-rewards/CrowdloanInterface.sol){target=\_blank} | {{networks.moonriver.precompiles.crowdloan}} |
| [ERC-20 Interface](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/balances-erc20/ERC20.sol){target=\_blank} | {{networks.moonriver.precompiles.erc20}} |
| Democracy [Removed] | {{networks.moonriver.precompiles.democracy}} |
| [X-Tokens](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xtokens/Xtokens.sol){target=\_blank} | {{networks.moonriver.precompiles.xtokens}} |
| [Relay Encoder](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/relay-encoder/RelayEncoder.sol){target=\_blank} | {{networks.moonriver.precompiles.relay_encoder}} |
| [XCM Transactor V1](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v1/XcmTransactorV1.sol){target=\_blank} | {{networks.moonriver.precompiles.xcm_transactor_v1}} |
| [Author Mapping](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/author-mapping/AuthorMappingInterface.sol){target=\_blank} | {{networks.moonriver.precompiles.author_mapping}} |
| [Batch](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/batch/Batch.sol){target=\_blank} | {{networks.moonriver.precompiles.batch}} |
| [Randomness](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/randomness/Randomness.sol){target=\_blank} | {{networks.moonriver.precompiles.randomness}} |
| [Call Permit](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/call-permit/CallPermit.sol){target=\_blank} | {{networks.moonriver.precompiles.call_permit}} |
| [Proxy](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/proxy/Proxy.sol){target=\_blank} | {{networks.moonriver.precompiles.proxy}} |
| [XCM Utilities](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-utils/XcmUtils.sol){target=\_blank} | {{networks.moonriver.precompiles.xcm_utils}} |
| [XCM Transactor V2](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v2/XcmTransactorV2.sol){target=\_blank} | {{networks.moonriver.precompiles.xcm_transactor_v2}} |
| [Council Collective [Removed]](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonriver.precompiles.collective_council}} |
| [Technical Committee Collective [Removed]](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonriver.precompiles.collective_tech_committee}} |
| [Treasury Council Collective](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonriver.precompiles.collective_treasury}} |
| [Referenda](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/referenda/Referenda.sol){target=\_blank} | {{networks.moonriver.precompiles.referenda}} |
| [Conviction Voting](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/conviction-voting/ConvictionVoting.sol){target=\_blank} | {{networks.moonriver.precompiles.conviction_voting}} |
| [Preimage](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/preimage/Preimage.sol){target=\_blank} | {{networks.moonriver.precompiles.preimage}} |
| [OpenGov Tech Committee](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonriver.precompiles.collective_opengov_tech_committee}} |
| [Precompile Registry](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/precompile-registry/PrecompileRegistry.sol){target=\_blank} | {{networks.moonriver.precompiles.registry}} |
| [GMP](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/gmp/Gmp.sol){target=\_blank} | {{networks.moonriver.precompiles.gmp}} |
| [XCM Transactor V3](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v3/XcmTransactorV3.sol){target=\_blank} | {{networks.moonriver.precompiles.xcm_transactor_v3}} |
| [Identity](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/identity/Identity.sol){target=\_blank} | {{networks.moonriver.precompiles.identity}} |
| [XCM Interface](https://github.com/Moonsong-Labs/moonkit/blob/main/precompiles/pallet-xcm/XcmInterface.sol){target=\_blank} | {{networks.moonriver.precompiles.xcm_interface}} |
=== "Moonbase Alpha"
| Contract | Address |
|:-------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------:|
| [Parachain Staking](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/parachain-staking/StakingInterface.sol){target=\_blank} | {{networks.moonbase.precompiles.staking}} |
| [Crowdloan Rewards](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/crowdloan-rewards/CrowdloanInterface.sol){target=\_blank} | {{networks.moonbase.precompiles.crowdloan}} |
| [ERC-20 Interface](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/balances-erc20/ERC20.sol){target=\_blank} | {{networks.moonbase.precompiles.erc20}} |
| Democracy [Removed] | {{networks.moonbase.precompiles.democracy}} |
| [X-Tokens](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xtokens/Xtokens.sol){target=\_blank} | {{networks.moonbase.precompiles.xtokens}} |
| [Relay Encoder](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/relay-encoder/RelayEncoder.sol){target=\_blank} | {{networks.moonbase.precompiles.relay_encoder}} |
| [XCM Transactor V1](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v1/XcmTransactorV1.sol){target=\_blank} | {{networks.moonbase.precompiles.xcm_transactor_v1}} |
| [Author Mapping](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/author-mapping/AuthorMappingInterface.sol){target=\_blank} | {{networks.moonbase.precompiles.author_mapping}} |
| [Batch](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/batch/Batch.sol){target=\_blank} | {{networks.moonbase.precompiles.batch}} |
| [Randomness](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/randomness/Randomness.sol){target=\_blank} | {{networks.moonbase.precompiles.randomness}} |
| [Call Permit](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/call-permit/CallPermit.sol){target=\_blank} | {{networks.moonbase.precompiles.call_permit}} |
| [Proxy](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/proxy/Proxy.sol){target=\_blank} | {{networks.moonbase.precompiles.proxy}} |
| [XCM Utilities](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-utils/XcmUtils.sol){target=\_blank} | {{networks.moonbase.precompiles.xcm_utils}} |
| [XCM Transactor V2](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v2/XcmTransactorV2.sol){target=\_blank} | {{networks.moonbase.precompiles.xcm_transactor_v2}} |
| [Council Collective [Removed]](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbase.precompiles.collective_council}} |
| [Technical Committee Collective [Removed]](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbase.precompiles.collective_tech_committee}} |
| [Treasury Council Collective](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbase.precompiles.collective_treasury}} |
| [Referenda](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/referenda/Referenda.sol){target=\_blank} | {{networks.moonbase.precompiles.referenda}} |
| [Conviction Voting](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/conviction-voting/ConvictionVoting.sol){target=\_blank} | {{networks.moonbase.precompiles.conviction_voting}} |
| [Preimage](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/preimage/Preimage.sol){target=\_blank} | {{networks.moonbase.precompiles.preimage}} |
| [OpenGov Tech Committee](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbase.precompiles.collective_opengov_tech_committee}} |
| [Precompile Registry](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/precompile-registry/PrecompileRegistry.sol){target=\_blank} | {{networks.moonbase.precompiles.registry}} |
| [GMP](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/gmp/Gmp.sol){target=\_blank} | {{networks.moonbase.precompiles.gmp}} |
| [XCM Transactor V3](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v3/XcmTransactorV3.sol){target=\_blank} | {{networks.moonbase.precompiles.xcm_transactor_v3}} |
| [Identity](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/identity/Identity.sol){target=\_blank} | {{networks.moonbase.precompiles.identity}} |
| [XCM Interface](https://github.com/Moonsong-Labs/moonkit/blob/main/precompiles/pallet-xcm/XcmInterface.sol){target=\_blank} | {{networks.moonbase.precompiles.xcm_interface}} |
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/ethereum/json-rpc/eth-rpc/
--- BEGIN CONTENT ---
---
title: Standard Ethereum JSON-RPC Methods
description: Explore a comprehensive list of standard Ethereum JSON-RPC methods that can be used to interface with Moonbeam nodes programmatically.
categories: JSON-RPC APIs, Reference, Ethereum Toolkit
---
# Supported Ethereum RPC Methods
## Introduction {: #introduction }
The Moonbeam team has collaborated closely with [Parity](https://www.parity.io){target=\_blank} on developing [Frontier](/learn/platform/technology/#frontier){target=\_blank}, an Ethereum compatibility layer for Substrate-based chains. This layer enables developers to run unmodified Ethereum dApps on Moonbeam seamlessly.
Nevertheless, not all Ethereum JSON-RPC methods are supported; some of those supported return default values (those related to Ethereum's PoW consensus mechanism in particular). This guide provides a comprehensive list of supported Ethereum JSON-RPC methods on Moonbeam. Developers can quickly reference this list to understand the available functionality for interfacing with Moonbeam's Ethereum-compatible blockchain.
## Standard Ethereum JSON-RPC Methods {: #basic-rpc-methods }
The basic JSON-RPC methods from the Ethereum API supported by Moonbeam are:
- **[eth_protocolVersion](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_protocolversion){target=\_blank}** — returns `1` by default
- **[eth_syncing](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_syncing){target=\_blank}** — returns an object with data about the sync status or `false`
- **[eth_hashrate](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_hashrate){target=\_blank}** — returns `"0x0"` by default
- **[eth_coinbase](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_coinbase){target=\_blank}** — returns the latest block author. Not necessarily a finalized block
- **[eth_mining](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_mining){target=\_blank}** — returns `false` by default
- **[eth_chainId](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_chainid){target=\_blank}** — returns the chain ID used for signing at the current block
- **[eth_gasPrice](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gasprice){target=\_blank}** — returns the base fee per unit of gas used. This is currently the minimum gas price for each network
- **[eth_accounts](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_accounts){target=\_blank}** — returns a list of addresses owned by the client
- **[eth_blockNumber](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_blocknumber){target=\_blank}** — returns the highest available block number
- **[eth_getBalance](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getbalance){target=\_blank}** — returns the balance of the given address. Instead of providing a block number as a parameter, you can provide a [default block parameter](#default-block-parameters)
- **[eth_getStorageAt](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getstorageat){target=\_blank}** — returns the content of the storage at a given address. Instead of providing a block number as a parameter, you can provide a [default block parameter](#default-block-parameters)
- **[eth_getBlockByHash](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblockbyhash){target=\_blank}** — returns information about the block of the given hash, including `baseFeePerGas` on post-London blocks
- **[eth_getBlockByNumber](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblockbynumber){target=\_blank}** — returns information about the block specified by block number, including `baseFeePerGas` on post-London blocks. Instead of providing a block number as the first parameter, you can provide a [default block parameter](#default-block-parameters)
- **[eth_getBlockReceipts](https://www.alchemy.com/docs/node/ethereum/ethereum-api-endpoints/eth-get-block-receipts){target=\_blank}** — returns all transaction receipts for a given block
- **[eth_getTransactionCount](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactioncount){target=\_blank}** — returns the number of transactions sent from the given address (nonce). Instead of providing a block number as a parameter, you can provide a [default block parameter](#default-block-parameters)
- **[eth_getBlockTransactionCountByHash](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbyhash){target=\_blank}** — returns the number of transactions in a block with a given block hash
- **[eth_getBlockTransactionCountByNumber](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbynumber){target=\_blank}** — returns the number of transactions in a block with a given block number
- **[eth_getUncleCountByBlockHash](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getunclecountbyblockhash){target=\_blank}** — returns `"0x0"` by default
- **[eth_getUncleCountByBlockNumber](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getunclecountbyblocknumber){target=\_blank}** — returns `"0x0"` by default
- **[eth_getCode](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getcode){target=\_blank}** — returns the code at the given address at the given block number. Instead of providing a block number as a parameter, you can provide a [default block parameter](#default-block-parameters)
- **[eth_sendTransaction](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendtransaction){target=\_blank}** — creates a new message call transaction or a contract creation, if the data field contains code. Returns the transaction hash or the zero hash if the transaction is not yet available
- **[eth_sendRawTransaction](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendrawtransaction){target=\_blank}** — creates a new message call transaction or a contract creation for signed transactions. Returns the transaction hash or the zero hash if the transaction is not yet available
- **[eth_call](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_call){target=\_blank}** — executes a new message call immediately without creating a transaction on the blockchain, returning the value of the executed call
- Moonbeam supports the use of the optional _state override set_ object. This address-to-state mapping object allows the user to specify some state to be ephemerally overridden before executing a call to `eth_call`. The state override set is commonly used for tasks like debugging smart contracts. Visit the [go-ethereum](https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-eth#:~:text=Object%20%2D%20State%20override%20set){target=\_blank} documentation to learn more
- Instead of providing a block number as a parameter, you can provide a [default block parameter](#default-block-parameters)
- **[eth_estimateGas](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_estimategas){target=\_blank}** — returns an estimated amount of gas necessary for a given transaction to succeed. You can optionally specify a `gasPrice` or `maxFeePerGas` and `maxPriorityFeePerGas`. Instead of providing a block number as a parameter, you can provide a [default block parameter](#default-block-parameters)
- **[eth_maxPriorityFeePerGas](https://www.alchemy.com/docs/node/ethereum/ethereum-api-endpoints/eth-max-priority-fee-per-gas){target=\_blank}** - returns an estimate of how much priority fee, in Wei, is needed for inclusion in a block
- **[eth_feeHistory](https://www.alchemy.com/docs/node/ethereum/ethereum-api-endpoints/eth-fee-history){target=\_blank}** — returns `baseFeePerGas`, `gasUsedRatio`, `oldestBlock`, and `reward` for a specified range of up to 1024 blocks
- **[eth_getTransactionByHash](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionbyhash){target=\_blank}** — returns the information about a transaction with a given hash. EIP-1559 transactions have `maxPriorityFeePerGas` and `maxFeePerGas` fields
- **[eth_getTransactionByBlockHashAndIndex](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionbyblockhashandindex){target=\_blank}** — returns information about a transaction at a given block hash and a given index position. EIP-1559 transactions have `maxPriorityFeePerGas` and `maxFeePerGas` fields
- **[eth_getTransactionByBlockNumberAndIndex](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionbyblocknumberandindex){target=\_blank}** — returns information about a transaction at a given block number and a given index position. EIP-1559 transactions have `maxPriorityFeePerGas` and `maxFeePerGas` fields. Instead of providing a block number as a parameter, you can provide a [default block parameter](#default-block-parameters)
- **[eth_getTransactionReceipt](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionreceipt){target=\_blank}** — returns the transaction receipt of a given transaction hash
- **[eth_getUncleByBlockHashAndIndex](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getunclebyblockhashandindex){target=\_blank}** — returns `null` by default
- **[eth_getUncleByBlockNumberAndIndex](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getunclebyblocknumberandindex){target=\_blank}** — returns `null` by default
- **[eth_getLogs](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getlogs){target=\_blank}** — returns an array of all logs matching a given filter object. Instead of providing a block number as a parameter, you can provide a [default block parameter](#default-block-parameters)
- **[eth_newFilter](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_newfilter){target=\_blank}** — creates a filter object based on the input provided. Returns a filter ID
- **[eth_newBlockFilter](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_newblockfilter){target=\_blank}** — creates a filter in the node to notify when a new block arrives. Returns a filter ID
- **[eth_newPendingTransactionFilter](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_newpendingtransactionfilter){target=\_blank}** - creates a filter in the node to notify when new pending transactions arrive. Returns a filter ID
- **[eth_getFilterChanges](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getfilterchanges){target=\_blank}** — polling method for filters (see methods above). Returns an array of logs that occurred since the last poll
- **[eth_getFilterLogs](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getfilterlogs){target=\_blank}** — returns an array of all the logs matching the filter with a given ID
- **[eth_uninstallFilter](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_uninstallfilter){target=\_blank}** — uninstall a filter with a given ID. It should be used when polling is no longer needed. Filters timeout when they are not requested using `eth_getFilterChanges` after some time
## Default Block Parameters {: #default-block-parameters }
Moonbeam supports several default block parameters that allow you to query a subset of JSON-RPC methods at significant block heights. Moonbeam supports the following default block parameters:
- `finalized` - Refers to the most recent block that Polkadot validators have finalized
- `safe` - Synonymous with `finalized` in Moonbeam. In Ethereum, `safe` refers to the most recent block that is considered safe by the network, meaning it is unlikely to be reverted but has not yet been finalized. With Moonbeam's fast and deterministic finality, `finalized` and `safe` refer to the same blocks.
- `earliest` - Refers to the genesis block of the blockchain
- `pending` - Represents the latest state, including pending transactions that have not yet been mined into a block. This is a live view of the mempool
- `latest` - Refers to the latest confirmed block in the blockchain, which may not be finalized
## Unsupported Ethereum JSON-RPC Methods {: #unsupported-rpc-methods }
Moonbeam does not support the following Ethereum API JSON-RPC methods:
- **[eth_getProof](https://www.alchemy.com/docs/node/ethereum/ethereum-api-endpoints/eth-get-proof){target=\_blank}** - returns the account and storage values of the specified account including the Merkle-proof
- **[eth_blobBaseFee](https://www.quicknode.com/docs/ethereum/eth_blobBaseFee){target=\_blank}** - returns the expected base fee for blobs in the next block
- **[eth_createAccessList](https://www.alchemy.com/docs/node/ethereum/ethereum-api-endpoints/eth-create-access-list){target=\_blank}** - creates an EIP-2930 type `accessList` based on a given transaction object
- **[eth_sign](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign){target=\_blank}** - allows the user to sign an arbitrary hash to be sent at a later time. Presents a [security risk](https://support.metamask.io/privacy-and-security/what-is-eth_sign-and-why-is-it-a-risk/){target=\_blank} as the arbitrary hash can be fraudulently applied to other transactions
- **[eth_signTransaction](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_signtransaction){target=\_blank}** - allows the user to sign a transaction to be sent at a later time. It is rarely used due to associated security risks
## Additional RPC Methods {: #additional-rpc-methods }
Check out some of the non-standard Ethereum and Moonbeam-specific RPC methods:
- [Debug and Trace](/builders/ethereum/json-rpc/debug-trace/)
- [Event Subscription](/builders/ethereum/json-rpc/pubsub/)
- [Custom Moonbeam](/builders/ethereum/json-rpc/moonbeam-custom-api/)
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/ethereum/json-rpc/moonbeam-custom-api/
--- BEGIN CONTENT ---
---
title: Moonbeam-specific RPC Methods
description: Discover Moonbeam's specialized API endpoints, featuring custom JSON-RPC methods designed exclusively for Moonbeam functionality.
categories: JSON-RPC APIs, Reference
---
# Moonbeam Custom API
## Introduction {: #introduction }
Moonbeam nodes include support for custom JSON-RPC endpoints:
- `moon_isBlockFinalized`
- `moon_isTxFinalized`
- `moon_getEthSyncBlockRange`
These endpoints provide valuable functionality for checking the finality of on-chain events.
To begin exploring Moonbeam's custom JSON-RPC endpoints, you can try out the provided curl examples below. These examples demonstrate how to query the public RPC endpoint of Moonbase Alpha. However, you can easily modify them to use with your own Moonbeam or Moonriver endpoint by changing the URL and API key. If you haven't already, you can obtain your endpoint and API key from one of our supported [Endpoint Providers](/builders/get-started/endpoints/){target=\_blank}.
## Supported Custom RPC Methods {: #rpc-methods }
???+ function "moon_isBlockFinalized"
Checks for the finality of the block given by its block hash.
=== "Parameters"
- `block_hash` *string* - the hash of the block, accepts either Substrate-style or Ethereum-style block hash as its input
=== "Returns"
Returns a boolean: `true` if the block is finalized, `false` if the block is not finalized or not found.
=== "Example"
```bash
curl -H "Content-Type: application/json" -X POST --data '{
"jsonrpc": "2.0",
"id": "1",
"method": "moon_isBlockFinalized",
"params": ["INSERT_BLOCK_HASH"]
}' {{ networks.moonbase.rpc_url }}
```
???+ function "moon_isTxFinalized"
Checks for the finality of a transaction given its EVM transaction hash.
=== "Parameters"
- `tx_hash` *string* - the EVM transaction hash of the transaction
=== "Returns"
Returns a boolean: `true` if the transaction is finalized, `false` if the transaction is not finalized or not found.
=== "Example"
```bash
curl -H "Content-Type: application/json" -X POST --data '{
"jsonrpc": "2.0",
"id": "1",
"method": "moon_isTxFinalized",
"params": ["INSERT_TRANSACTION_HASH"]
}' {{ networks.moonbase.rpc_url }}
```
???+ function "moon_getEthSyncBlockRange"
Returns the range of blocks that are fully indexed in Frontier's backend.
=== "Parameters"
None
=== "Returns"
Returns the range of blocks that are fully indexed in Frontier's backend. An example response below includes the Substrate block hashes of block `0` and the latest fully indexed block:
```[
"0x91bc6e169807aaa54802737e1c504b2577d4fafedd5a02c10293b1cd60e39527",
"0xb1b49bd709ca9fe0e751b8648951ffbb2173e1258b8de8228cfa0ab27003f612"
]```
=== "Example"
```bash
curl -H "Content-Type: application/json" -X POST --data '{
"jsonrpc": "2.0",
"id": "1",
"method": "moon_getEthSyncBlockRange",
"params": []
}' {{ networks.moonbase.rpc_url }}
```
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/ethereum/precompiles/overview/
--- BEGIN CONTENT ---
---
title: Solidity Precompiles
description: An overview of the available Solidity precompiles on Moonbeam. Precompiles enable you to interact with Substrate features using the Ethereum API.
categories: Reference, Basics
---
# Overview of the Precompiled Contracts on Moonbeam
## Overview {: #introduction }
On Moonbeam, a precompiled contract is native Substrate code that has an Ethereum-style address and can be called using the Ethereum API, like any other smart contract. The precompiles allow you to call the Substrate runtime directly which is not normally accessible from the Ethereum side of Moonbeam.
The Substrate code responsible for implementing precompiles can be found in the [EVM pallet](/learn/platform/technology/#evm-pallet){target=\_blank}. The EVM pallet includes the [standard precompiles found on Ethereum and some additional precompiles that are not specific to Ethereum](https://github.com/polkadot-evm/frontier/tree/master/frame/evm/precompile){target=\_blank}. It also provides the ability to create and execute custom precompiles through the generic [`Precompiles` trait](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm/trait.Precompile.html){target=\_blank}. There are several custom Moonbeam-specific precompiles that have been created, all of which can be found in the [Moonbeam codebase](https://github.com/moonbeam-foundation/moonbeam/tree/master/precompiles){target=\_blank}. It is important to highlight that the precompiles from this list with the `CallableByContract` check are not callable inside the contract constructor.
The Ethereum precompiled contracts contain complex functionality that is computationally intensive, such as hashing and encryption. The custom precompiled contracts on Moonbeam provide access to Substrate-based functionality such as staking, governance, XCM-related functions, and more.
The Moonbeam-specific precompiles can be interacted with through familiar and easy-to-use Solidity interfaces using the Ethereum API, which are ultimately used to interact with the underlying Substrate interface. This flow is depicted in the following diagram:

!!! note
There can be some unintended consequences when using the precompiled contracts on Moonbeam. Please refer to the [Security Considerations](/learn/core-concepts/security/){target=\_blank} page for more information.
## Precompiled Contract Addresses {: #precompiled-contract-addresses }
The precompiled contracts are categorized by address and based on the origin network. If you were to convert the precompiled addresses to decimal format, and break them into categories by numeric value, the categories are as follows:
- **0-1023** - [Ethereum MainNet precompiles](#ethereum-mainnet-precompiles)
- **1024-2047** - precompiles that are [not in Ethereum and not Moonbeam specific](#non-moonbeam-specific-nor-ethereum-precomiles)
- **2048-4095** - [Moonbeam specific precompiles](#moonbeam-specific-precompiles)
### Ethereum MainNet Precompiles {: #ethereum-mainnet-precompiles }
=== "Moonbeam"
| Contract | Address |
|:---------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [ECRECOVER](/builders/ethereum/precompiles/utility/eth-mainnet/#verify-signatures-with-ecrecover){target=\_blank} | 0x0000000000000000000000000000000000000001 |
| [SHA256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha256){target=\_blank} | 0x0000000000000000000000000000000000000002 |
| [RIPEMD160](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-ripemd-160){target=\_blank} | 0x0000000000000000000000000000000000000003 |
| [Identity](/builders/ethereum/precompiles/utility/eth-mainnet/#the-identity-function){target=\_blank} | 0x0000000000000000000000000000000000000004 |
| [Modular Exponentiation](/builders/ethereum/precompiles/utility/eth-mainnet/#modular-exponentiation){target=\_blank} | 0x0000000000000000000000000000000000000005 |
| [BN128Add](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128add){target=\_blank} | 0x0000000000000000000000000000000000000006 |
| [BN128Mul](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128mul){target=\_blank} | 0x0000000000000000000000000000000000000007 |
| [BN128Pairing](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128pairing){target=\_blank} | 0x0000000000000000000000000000000000000008 |
| [Blake2](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_blake2/struct.Blake2F.html){target=\_blank} | 0x0000000000000000000000000000000000000009 |
| [P256Verify](https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md){target=\_blank} | 0x0000000000000000000000000000000000000100 |
=== "Moonriver"
| Contract | Address |
|:---------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [ECRECOVER](/builders/ethereum/precompiles/utility/eth-mainnet/#verify-signatures-with-ecrecover){target=\_blank} | 0x0000000000000000000000000000000000000001 |
| [SHA256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha256){target=\_blank} | 0x0000000000000000000000000000000000000002 |
| [RIPEMD160](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-ripemd-160){target=\_blank} | 0x0000000000000000000000000000000000000003 |
| [Identity](/builders/ethereum/precompiles/utility/eth-mainnet/#the-identity-function){target=\_blank} | 0x0000000000000000000000000000000000000004 |
| [Modular Exponentiation](/builders/ethereum/precompiles/utility/eth-mainnet/#modular-exponentiation){target=\_blank} | 0x0000000000000000000000000000000000000005 |
| [BN128Add](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128add){target=\_blank} | 0x0000000000000000000000000000000000000006 |
| [BN128Mul](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128mul){target=\_blank} | 0x0000000000000000000000000000000000000007 |
| [BN128Pairing](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128pairing){target=\_blank} | 0x0000000000000000000000000000000000000008 |
| [Blake2](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_blake2/struct.Blake2F.html){target=\_blank} | 0x0000000000000000000000000000000000000009 |
| [P256Verify](https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md){target=\_blank} | 0x0000000000000000000000000000000000000100 |
=== "Moonbase Alpha"
| Contract | Address |
|:---------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [ECRECOVER](/builders/ethereum/precompiles/utility/eth-mainnet/#verify-signatures-with-ecrecover){target=\_blank} | 0x0000000000000000000000000000000000000001 |
| [SHA256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha256){target=\_blank} | 0x0000000000000000000000000000000000000002 |
| [RIPEMD160](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-ripemd-160){target=\_blank} | 0x0000000000000000000000000000000000000003 |
| [Identity](/builders/ethereum/precompiles/utility/eth-mainnet/#the-identity-function){target=\_blank} | 0x0000000000000000000000000000000000000004 |
| [Modular Exponentiation](/builders/ethereum/precompiles/utility/eth-mainnet/#modular-exponentiation){target=\_blank} | 0x0000000000000000000000000000000000000005 |
| [BN128Add](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128add){target=\_blank} | 0x0000000000000000000000000000000000000006 |
| [BN128Mul](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128mul){target=\_blank} | 0x0000000000000000000000000000000000000007 |
| [BN128Pairing](/builders/ethereum/precompiles/utility/eth-mainnet/#bn128pairing){target=\_blank} | 0x0000000000000000000000000000000000000008 |
| [Blake2](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_blake2/struct.Blake2F.html){target=\_blank} | 0x0000000000000000000000000000000000000009 |
| [P256Verify](https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md){target=\_blank} | 0x0000000000000000000000000000000000000100 |
### Non-Moonbeam Specific nor Ethereum Precompiles {: #non-moonbeam-specific-nor-ethereum-precompiles }
=== "Moonbeam"
| Contract | Address |
|:--------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [SHA3FIPS256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha3fips256){target=\_blank} | 0x0000000000000000000000000000000000000400 |
| Dispatch [Removed] | 0x0000000000000000000000000000000000000401 |
| [ECRecoverPublicKey](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_simple/struct.ECRecoverPublicKey.html){target=\_blank} | 0x0000000000000000000000000000000000000402 |
=== "Moonriver"
| Contract | Address |
|:--------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [SHA3FIPS256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha3fips256){target=\_blank} | 0x0000000000000000000000000000000000000400 |
| Dispatch [Removed] | 0x0000000000000000000000000000000000000401 |
| [ECRecoverPublicKey](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_simple/struct.ECRecoverPublicKey.html){target=\_blank} | 0x0000000000000000000000000000000000000402 |
=== "Moonbase Alpha"
| Contract | Address |
|:-------------------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| [SHA3FIPS256](/builders/ethereum/precompiles/utility/eth-mainnet/#hashing-with-sha3fips256){target=\_blank} | 0x0000000000000000000000000000000000000400 |
| Dispatch [Removed] | 0x0000000000000000000000000000000000000401 |
| [ECRecoverPublicKey](https://polkadot-evm.github.io/frontier/rustdocs/pallet_evm_precompile_simple/struct.ECRecoverPublicKey.html){target=\_blank} | 0x0000000000000000000000000000000000000402 |
### Moonbeam Specific Precompiles {: #moonbeam-specific-precompiles }
=== "Moonbeam"
| Contract | Address |
|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------:|
| [Parachain Staking](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/parachain-staking/StakingInterface.sol){target=\_blank} | {{networks.moonbeam.precompiles.staking}} |
| [Crowdloan Rewards](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/crowdloan-rewards/CrowdloanInterface.sol){target=\_blank} | {{networks.moonbeam.precompiles.crowdloan}} |
| [ERC-20 Interface](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/balances-erc20/ERC20.sol){target=\_blank} | {{networks.moonbeam.precompiles.erc20}} |
| Democracy [Removed] | {{networks.moonbeam.precompiles.democracy}} |
| [X-Tokens](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xtokens/Xtokens.sol){target=\_blank} | {{networks.moonbeam.precompiles.xtokens}} |
| [Relay Encoder](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/relay-encoder/RelayEncoder.sol){target=\_blank} | {{networks.moonbeam.precompiles.relay_encoder}} |
| [XCM Transactor V1](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v1/XcmTransactorV1.sol){target=\_blank} | {{networks.moonbeam.precompiles.xcm_transactor_v1}} |
| [Author Mapping](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/author-mapping/AuthorMappingInterface.sol){target=\_blank} | {{networks.moonbeam.precompiles.author_mapping}} |
| [Batch](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/batch/Batch.sol){target=\_blank} | {{networks.moonbeam.precompiles.batch}} |
| [Randomness](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/randomness/Randomness.sol){target=\_blank} | {{networks.moonbeam.precompiles.randomness}} |
| [Call Permit](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/call-permit/CallPermit.sol){target=\_blank} | {{networks.moonbeam.precompiles.call_permit}} |
| [Proxy](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/proxy/Proxy.sol){target=\_blank} | {{networks.moonbeam.precompiles.proxy}} |
| [XCM Utilities](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-utils/XcmUtils.sol){target=\_blank} | {{networks.moonbeam.precompiles.xcm_utils}} |
| [XCM Transactor V2](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v2/XcmTransactorV2.sol){target=\_blank} | {{networks.moonbeam.precompiles.xcm_transactor_v2}} |
| [Council Collective [Removed]](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbeam.precompiles.collective_council}} |
| [Technical Committee Collective [Removed]](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbeam.precompiles.collective_tech_committee}} |
| [Treasury Council Collective](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbeam.precompiles.collective_treasury}} |
| [Referenda](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/referenda/Referenda.sol){target=\_blank} | {{networks.moonbeam.precompiles.referenda}} |
| [Conviction Voting](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/conviction-voting/ConvictionVoting.sol){target=\_blank} | {{networks.moonbeam.precompiles.conviction_voting}} |
| [Preimage](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/preimage/Preimage.sol){target=\_blank} | {{networks.moonbeam.precompiles.preimage}} |
| [OpenGov Tech Committee](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbeam.precompiles.collective_opengov_tech_committee}} |
| [Precompile Registry](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/precompile-registry/PrecompileRegistry.sol){target=\_blank} | {{networks.moonbeam.precompiles.registry}} |
| [GMP](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/gmp/Gmp.sol){target=\_blank} | {{networks.moonbeam.precompiles.gmp}} |
| [XCM Transactor V3](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v3/XcmTransactorV3.sol){target=\_blank} | {{networks.moonbeam.precompiles.xcm_transactor_v3}} |
| [XCM interface](https://github.com/Moonsong-Labs/moonkit/blob/main/precompiles/pallet-xcm/XcmInterface.sol){target=\_blank} | {{networks.moonbeam.precompiles.xcm_interface}} |
| [Identity](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/identity/Identity.sol){target=\_blank} | {{networks.moonbeam.precompiles.identity}} |
=== "Moonriver"
| Contract | Address |
|:-------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------:|
| [Parachain Staking](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/parachain-staking/StakingInterface.sol){target=\_blank} | {{networks.moonriver.precompiles.staking}} |
| [Crowdloan Rewards](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/crowdloan-rewards/CrowdloanInterface.sol){target=\_blank} | {{networks.moonriver.precompiles.crowdloan}} |
| [ERC-20 Interface](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/balances-erc20/ERC20.sol){target=\_blank} | {{networks.moonriver.precompiles.erc20}} |
| Democracy [Disabled] | {{networks.moonriver.precompiles.democracy}} |
| [X-Tokens](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xtokens/Xtokens.sol){target=\_blank} | {{networks.moonriver.precompiles.xtokens}} |
| [Relay Encoder](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/relay-encoder/RelayEncoder.sol){target=\_blank} | {{networks.moonriver.precompiles.relay_encoder}} |
| [XCM Transactor V1](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v1/XcmTransactorV1.sol){target=\_blank} | {{networks.moonriver.precompiles.xcm_transactor_v1}} |
| [Author Mapping](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/author-mapping/AuthorMappingInterface.sol){target=\_blank} | {{networks.moonriver.precompiles.author_mapping}} |
| [Batch](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/batch/Batch.sol){target=\_blank} | {{networks.moonriver.precompiles.batch}} |
| [Randomness](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/randomness/Randomness.sol){target=\_blank} | {{networks.moonriver.precompiles.randomness}} |
| [Call Permit](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/call-permit/CallPermit.sol){target=\_blank} | {{networks.moonriver.precompiles.call_permit}} |
| [Proxy](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/proxy/Proxy.sol){target=\_blank} | {{networks.moonriver.precompiles.proxy}} |
| [XCM Utilities](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-utils/XcmUtils.sol){target=\_blank} | {{networks.moonriver.precompiles.xcm_utils}} |
| [XCM Transactor V2](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v2/XcmTransactorV2.sol){target=\_blank} | {{networks.moonriver.precompiles.xcm_transactor_v2}} |
| [Council Collective [Removed]](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonriver.precompiles.collective_council}} |
| [Technical Committee Collective [Removed]](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonriver.precompiles.collective_tech_committee}} |
| [Treasury Council Collective](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonriver.precompiles.collective_treasury}} |
| [Referenda](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/referenda/Referenda.sol){target=\_blank} | {{networks.moonriver.precompiles.referenda}} |
| [Conviction Voting](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/conviction-voting/ConvictionVoting.sol){target=\_blank} | {{networks.moonriver.precompiles.conviction_voting}} |
| [Preimage](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/preimage/Preimage.sol){target=\_blank} | {{networks.moonriver.precompiles.preimage}} |
| [OpenGov Tech Committee](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonriver.precompiles.collective_opengov_tech_committee}} |
| [Precompile Registry](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/precompile-registry/PrecompileRegistry.sol){target=\_blank} | {{networks.moonriver.precompiles.registry}} |
| [GMP](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/gmp/Gmp.sol){target=\_blank} | {{networks.moonriver.precompiles.gmp}} |
| [XCM Transactor V3](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v3/XcmTransactorV3.sol){target=\_blank} | {{networks.moonriver.precompiles.xcm_transactor_v3}} |
| [XCM interface](https://github.com/Moonsong-Labs/moonkit/blob/main/precompiles/pallet-xcm/XcmInterface.sol){target=\_blank} | {{networks.moonriver.precompiles.xcm_interface}} |
| [Identity](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/identity/Identity.sol){target=\_blank} | {{networks.moonriver.precompiles.identity}} |
=== "Moonbase Alpha"
| Contract | Address |
|:--------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------:|
| [Parachain Staking](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/parachain-staking/StakingInterface.sol){target=\_blank} | {{networks.moonbase.precompiles.staking}} |
| [Crowdloan Rewards](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/crowdloan-rewards/CrowdloanInterface.sol){target=\_blank} | {{networks.moonbase.precompiles.crowdloan}} |
| [ERC-20 Interface](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/balances-erc20/ERC20.sol){target=\_blank} | {{networks.moonbase.precompiles.erc20}} |
| Democracy [Removed] | {{networks.moonbase.precompiles.democracy}} |
| [X-Tokens](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xtokens/Xtokens.sol){target=\_blank} | {{networks.moonbase.precompiles.xtokens}} |
| [Relay Encoder](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/relay-encoder/RelayEncoder.sol){target=\_blank} | {{networks.moonbase.precompiles.relay_encoder}} |
| [XCM Transactor V1](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v1/XcmTransactorV1.sol){target=\_blank} | {{networks.moonbase.precompiles.xcm_transactor_v1}} |
| [Author Mapping](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/author-mapping/AuthorMappingInterface.sol){target=\_blank} | {{networks.moonbase.precompiles.author_mapping}} |
| [Batch](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/batch/Batch.sol){target=\_blank} | {{networks.moonbase.precompiles.batch}} |
| [Randomness](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/randomness/Randomness.sol){target=\_blank} | {{networks.moonbase.precompiles.randomness}} |
| [Call Permit](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/call-permit/CallPermit.sol){target=\_blank} | {{networks.moonbase.precompiles.call_permit}} |
| [Proxy](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/proxy/Proxy.sol){target=\_blank} | {{networks.moonbase.precompiles.proxy}} |
| [XCM Utilities](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-utils/XcmUtils.sol){target=\_blank} | {{networks.moonbase.precompiles.xcm_utils}} |
| [XCM Transactor V2](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v2/XcmTransactorV2.sol){target=\_blank} | {{networks.moonbase.precompiles.xcm_transactor_v2}} |
| [Council Collective [Removed]](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbase.precompiles.collective_council}} |
| [Technical Committee Collective [Removed]](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbase.precompiles.collective_tech_committee}} |
| [Treasury Council Collective](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbase.precompiles.collective_treasury}} |
| [Referenda](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/referenda/Referenda.sol){target=\_blank} | {{networks.moonbase.precompiles.referenda}} |
| [Conviction Voting](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/conviction-voting/ConvictionVoting.sol){target=\_blank} | {{networks.moonbase.precompiles.conviction_voting}} |
| [Preimage](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/preimage/Preimage.sol){target=\_blank} | {{networks.moonbase.precompiles.preimage}} |
| [OpenGov Tech Committee](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/collective/Collective.sol){target=\_blank} | {{networks.moonbase.precompiles.collective_opengov_tech_committee}} |
| [Precompile Registry](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/precompile-registry/PrecompileRegistry.sol){target=\_blank} | {{networks.moonbase.precompiles.registry}} |
| [GMP](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/gmp/Gmp.sol){target=\_blank} | {{networks.moonbase.precompiles.gmp}} |
| [XCM Transactor V3](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/xcm-transactor/src/v3/XcmTransactorV3.sol){target=\_blank} | {{networks.moonbase.precompiles.xcm_transactor_v3}} |
| [XCM Interface](https://github.com/Moonsong-Labs/moonkit/blob/main/precompiles/pallet-xcm/XcmInterface.sol){target=\_blank} | {{networks.moonbeam.precompiles.xcm_interface}} |
| [Identity](https://github.com/moonbeam-foundation/moonbeam/blob/master/precompiles/identity/Identity.sol){target=\_blank} | {{networks.moonbase.precompiles.identity}} |
--- END CONTENT ---
Doc-Content: https://docs.moonbeam.network/builders/get-started/endpoints/
--- BEGIN CONTENT ---
---
title: Moonbeam API Providers and Endpoints
description: Use one of the supported API providers to connect to a public endpoint or create custom JSON-RPC and WSS endpoints for Moonbeam-based networks.
categories: JSON-RPC APIs, Reference
---
# Network Endpoints
## Public Endpoints {: #public-endpoints }
Moonbeam-based networks have two endpoints available for users to connect to: one for HTTPS and one for WSS.
The endpoints in this section are for development purposes only and are not meant to be used in production applications.
If you are looking for an API provider suitable for production use, you can check out the [Endpoint Providers](#endpoint-providers) section of this guide.
### Moonbeam {: #moonbeam }
=== "HTTPS"
| Provider | RPC URL | Limits |
|:-----------:|:------------------------------------------------------------------:|:-----------:|
| Dwellir |
| 200 req/sec |
#### Relay Chain {: #relay-chain }
To connect to the Moonbase Alpha relay chain, you can use the following WS Endpoint:
| Provider | RPC URL |
|:--------:|:----------------------------------------------------------:|
| OpsLayer |
```wss://relay.api.moonbase.moonbeam.network```
|
## RPC Endpoint Providers {: #endpoint-providers }
You can create your own endpoint suitable for development or production use using any of the following API providers:
- [1RPC](#1rpc)
- [Blast](#blast)
- [Chainstack](#chainstack)
- [dRPC](#drpc)
- [Dwellir](#dwellir)
- [GetBlock](#getblock)
- [Grove](#grove)
- [OnFinality](#onfinality)
- [UnitedBloc](#unitedbloc)
### 1RPC {: #1rpc}
[1RPC](https://www.1rpc.io){target=_blank} is a free and private RPC relay that protects user privacy by preventing data collection, user tracking, phishing attempts from other parties. It tunnels user requests via distributed relays to other RPC providers whilst preventing the tracking of user metadata such as IP address, device information and wallet linkability with secure enclave technology.
1RPC is created to be an open initiative from the blockchain infrastructure community. They are motivated by a common good mission to help build a better Web3 and encourage anyone who values user privacy to join this open collaboration.
Head over to [1RPC](https://www.1rpc.io){target=_blank} official site to set it up!

### Blast {: #blast}
As a user of [Blast](https://blastapi.io){target=_blank} powered by Bware Labs, you will be able to obtain your own free endpoint allowing you to interact with Moonbeam, just by performing a few simple clicks within a user-friendly interface.
To get started, you'll need to head to [Blast](https://blastapi.io){target=_blank}, and launch the app, and connect your wallet. Once your wallet is connected you will be able to create a project and then generate your own custom endpoint. To generate an endpoint:
1. Create a new project
2. Click on **Available Endpoints**
3. Select Moonbeam network for your endpoint
4. Confirm the selected network and Press **Activate**
5. You'll now see Moonbeam under **Active Endpoints**. Click on the network and you'll see your custom RPC and WSS endpoints on the next page

### Chainstack {: #chainstack }
[Chainstack](https://chainstack.com/){target=_blank}, the Web3 infrastructure provider, offers free and paid endpoints for Moonbeam. The free Developer plan starts with 3 million monthly requests and 25 requests per second (RPS). You can easily scale with the paid plans.
To start with a free Developer plan endpoint, sign up using an email or any social account, like GitHub or X (Twitter).
1. Visit [Chainstack](https://console.chainstack.com/){target=_blank}
2. Sign up
3. Deploy a Moonbeam node

### dRPC.org {: #drpc }
dRPC.org offers public and paid [Moonbeam RPC](https://drpc.org/chainlist/moonbeam){target=_blank} endpoints, providing an efficient, low-latency connection to blockchain nodes. The paid tiers include higher request limits, lower latency, and advanced analytics for optimized performance.
How to use dRPC:
1. Sign up or log in at [dRPC.org](https://drpc.org/){target=_blank}
2. In the dashboard, create an API key
3. Click the key and select the desired endpoint
For 24/7 support, join dRPC's [Discord](https://drpc.org/discord){target=_blank}.
### Dwellir {: #dwellir }
[Dwellir](https://www.dwellir.com){target=_blank} is a blockchain operation service that ensures global scalability, low latency, and a 99.99% uptime guarantee, providing fast and reliable node operations wherever your business stands. The public endpoint service is geographically distributed bare metal servers globally. As the service is public, there are no sign-up or API keys to manage.
To get started with a developer endpoint or dedicated node, you'll need to contact us:
1. Visit [Dwellir](https://www.dwellir.com/contact){target=_blank}
2. Submit your **email** and your node request

### GetBlock {: #getblock }
[GetBlock](https://getblock.io){target=_blank} is a service that provides instant API access to Moonbeam and Moonriver and is available through shared and dedicated nodes. [Dedicated nodes](https://docs.getblock.io/getting-started/plans-and-limits/choosing-your-plan#dedicated-nodes){target=_blank} provide access to a private server with fast speeds and without rate limits. [Shared nodes](https://docs.getblock.io/getting-started/plans-and-limits/choosing-your-plan#shared-nodes){target=_blank} provide a free API/add-on based endpoint for you to get started quickly.
To get started with GetBlock, you can go to the [GetBlock registration page](https://account.getblock.io/sign-up){target=_blank} and sign up for a new account. Then, from your account **Dashboard**, you can view and manage your existing endpoints for multiple protocols, and also create new ones.
Creating a new API/add-on based endpoint is simple, all you have to do is:
1. Fill the information for the desired protocol from the list of available blockchains
2. Choose the network you want your endpoint to point to (**Mainnet**, **Testnet**, etc)
3. Select **JSON-RPC** from the **API/Add-on** dropdown
4. Click the **Get** button at the far right and you're all set to go!

### Grove {: #grove }
[Grove](https://grove.city){target=_blank} is a decentralized RPC network that provides reliable Web3 infrastructure with enterprise-grade performance and security. Grove offers both free and paid tiers, with the free tier providing generous limits for development use, while paid plans offer higher throughput, dedicated support, and advanced features for production applications. Grove's decentralized approach ensures high availability and censorship resistance by distributing requests across multiple node operators. The network supports both JSON-RPC and WebSocket connections for real-time applications. To get started with Grove:
1. Visit the [Grove Portal](https://portal.grove.city/){target=_blank} and sign up for an account
2. From your dashboard, create a new application
3. Copy your Moonbeam or Moonriver endpoints
4. Start making requests to your custom Grove endpoint
Grove provides detailed analytics, request monitoring, and flexible rate limiting to help you optimize your application's performance.

### OnFinality {: #onfinality }
[OnFinality](https://onfinality.io){target=_blank} provides a free API key based endpoint for customers in place of a public endpoint. Additionally, OnFinality offers paid tiers of service that offer increased rate limits and higher performance than those offered by the free tier. You also receive more in depth analytics of the usage of your application.
To create a custom OnFinality endpoint, go to [OnFinality](https://onfinality.io){target=_blank} and sign up, or if you already have signed up you can go ahead and log in. From the OnFinality **Dashboard**, you can:
1. Click on **API Service**
2. Select the network from the dropdown
3. Your custom API endpoint will be generated automatically

### UnitedBloc {: #unitedbloc }
[UnitedBloc](https://medium.com/unitedbloc/unitedbloc-rpc-c84972f69457){target=_blank} is a collective of community collators from both Moonbeam and Moonriver. To provide value for the community, they offer public RPC services for the Moonbeam, Moonriver, and Moonbase Alpha networks.
The public endpoint service is served by eight geographically distributed bare metal servers globally balanced via GeoDNS and regionally load balanced with NGINX. As the service is public, there are no sign-up or API keys to manage.
The collators involved in this initiative are:
- Blockshard (CH)
- BloClick (ES)
- BrightlyStake (IN)
- CertHum (US)
- GPValidator (PT)
- Hetavalidation (AU)
- Legend (AE)
- PathrockNetwork (DE)
- Polkadotters (CZ)
- SIK | crifferent.de (DE)
- StakeBaby (GR)
- StakeSquid (GE)
- TrueStaking (US)
They also provide a [public Grafana dashboard](https://monitoring.unitedbloc.com:3030/public-dashboards/7444d2ab76ee45eda181618b0f0ecb98?orgId=1){target=_blank} with some cool metrics.
Check the [public endpoints section](#public-endpoints) to get the relevant URL. You can contact them via their [Telegram channel](https://t.me/+tRvy3z5-Kp1mMGMx){target=_blank}, or read more about their initiative on their [blogpost page](https://medium.com/unitedbloc/unitedbloc-rpc-c84972f69457){target=_blank}.
## Lazy Loading with RPC Endpoint Providers {: #lazy-loading-with-RPC-Endpoint-Providers }
Lazy loading lets a Moonbeam node operate while downloading network state in the background, eliminating the need to wait for full synchronization before use. To spin up a Moonbeam node with lazy loading, you'll need to either [download the Moonbeam release binary](/node-operators/networks/run-a-node/systemd/#the-release-binary){target=_blank} or [compile the binary](/node-operators/networks/run-a-node/compile-binary/#compile-the-binary){target=_blank}. You can activate lazy loading with the following flag:
`--lazy-loading-remote-rpc 'INSERT-RPC-URL'`
Lazy loading is highly resource-intensive, requiring many RPC requests to function. To avoid being throttled, it's recommended that you use a [dedicated endpoint](#endpoint-providers) (i.e., an endpoint with an API key) rather than a public endpoint. You will likely be rate-limited if you use lazy loading with a public endpoint. Upon spooling up a node with this feature, you'll see output like the following:
[Lazy loading 🌗]
You are now running the Moonbeam client in lazy loading mode, where data is retrieved
from a live RPC node on demand.
Using remote state from: https://moonbeam.unitedbloc.com
Forking from block: 8482853
To ensure the client works properly, please note the following:
1. *Avoid Throttling*: Ensure that the backing RPC node is not limiting the number of
requests, as this can prevent the lazy loading client from functioning correctly;
2. *Be Patient*: As the client may take approximately 20 times longer than normal to
retrieve and process the necessary data for the requested operation.
The service will start in 10 seconds...
### Overriding State with Lazy Loading
By default, you won't see detailed logging in the terminal. To override this setting and show lazy loading logs, you can add the following flag to your command to start the Moonbeam node: `-l debug`. You can further customize your use of the lazy loading functionality with the following optional parameters:
- **`--lazy-loading-block`** - specifies a block hash from which to start loading data. If not provided, the latest block will be used
- **`--lazy-loading-delay-between-requests`** - the delay (in milliseconds) between RPC requests when using lazy loading. This parameter controls the amount of time to wait between consecutive RPC requests. This can help manage request rate and avoid overwhelming the server. Default value is `100` milliseconds
- **`--lazy-loading-max-retries-per-request`** - the maximum number of retries for an RPC request when using lazy loading. Default value is `10` retries
- **`--lazy-loading-runtime-override`** - path to a WASM file to override the runtime when forking. If not provided, it will fetch the runtime from the block being forked
- **`--lazy-loading-state-overrides`** - path to a JSON file containing state overrides to be applied when forking
#### Simple Storage Item Override
The state overrides file should define the respective pallet, storage item, and value that you seek to override as follows:
```json
[
{
"pallet": "System",
"storage": "SelectedCandidates",
"value": "0x04f24ff3a9cf04c71dbc94d0b566f7a27b94566cac"
}
]
```
#### Override an Account's Free Balance
To override the balance of a particular account, you can override the account storage item of the system pallet for the respective account as follows:
```json
[
{
"pallet": "System",
"storage": "Account",
"key": "TARGET_ADDRESS",
"value": "0x460c000002000000010000000600000069e10de76676d0800000000000000000040a556b0e032de12000000000000000004083a09e15c74c1b0100000000000000000000000000000000000000000000080"
}
]
```
??? note "Details about overriding account balances"
Overriding an account balance, as shown above, can be a complex process. However, this guide will break it down into steps that are easy to follow. Before making any changes, you should obtain the existing value corresponding to the key (i.e., the account in this case). You can go to [**Chain State** on Polkadot.js Apps](https://polkadot.js.org/apps/?rpc=wss://wss.api.moonbeam.network#/chainstate){target=_blank} and query the System pallet by providing the account you'd like to query. Upon submitting the query, you'll get back a readable account structure like so:
```text
{
nonce: 3,142
consumers: 2
providers: 1
sufficients: 6
data: {
free: 1,278,606,392,142,175,328,676
reserved: 348,052,500,000,000,000,000
frozen: 20,413,910,106,633,175,872
flags: 170,141,183,460,469,231,731,687,303,715,884,105,728
}
}
```
While this is useful as a reference, the information you're looking for is the encoded storage key, which is accessible even without submitting the chain state query. In this instance, the encoded storage key corresponding to the system pallet and the selected account `0x3B939FeaD1557C741Ff06492FD0127bd287A421e` is:
```text
0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9b882fedb4f75b055c709ec5b66b5d9933b939fead1557c741ff06492fd0127bd287a421e
```
Note that this encoded storage key will change alongside any input changes, such as a different account being queried. Then, head over the **Raw Storage** tab on [Polkadot.js Apps](https://polkadot.js.org/apps/#/chainstate/raw){target=_blank}. Input the above storage key and submit the query. The response is the SCALE encoded account struct, a part of which contains the free balance information to be modified as part of this example:
```text
0x460c0000020000000100000006000000a4d92a6a4e6b3a5045000000000000000040a556b0e032de12000000000000004083a09e15c74c1b010000000000000000000000000000000000000000000080
```
There is quite a bit of data encoded in the value field because it is a complex struct comprised of multiple values. The struct is comprised of:
```text
struct AccountInfo {
nonce: u32, // Transaction count
consumers: u32, // Number of consumers
providers: u32, // Number of providers
sufficients: u32, // Number of sufficients
data: AccountData { // The balance info
free: u128, // Free balance
reserved: u128, // Reserved balance
frozen: u128, // Frozen balance
flags: u128 // Account flags
}
}
```
You can associate each part of the SCALE encoded struct with the corresponding piece of Alice's account information that it represents:
```text
0x460c0000 // nonce (u32): 3,142
02000000 // consumers (u32): 2
01000000 // providers (u32): 1
06000000 // sufficients (u32): 6
a4d92a6a4e6b3a5045000000000000000
// free (u128): 1,278,606,392,142,175,328,676
40a556b0e032de1200000000000000000
// reserved (u128): 348,052,500,000,000,000,000
4083a09e15c74c1b01000000000000000
// frozen (u128): 20,413,910,106,633,175,872
00000000000000000000000000000080
// flags (u128): 170,141,183,460,469,231,731,687,303,715,884,105,728
```
Remember that the values are little endian encoded. To convert the hexadecimal little endian encoded values to decimal, you can use [Substrate Utilities converter](https://www.shawntabrizi.com/substrate-js-utilities/){target=_blank}, using the **Balance to Hex (Little Endian)** converter.
In this example, the existing free balance of `1,278,606,392,142,175,328,676` Wei or approximately `1278.60` DEV is `a4d92a6a4e6b3a5045`. The following example will change the value to `500,000` DEV, which is `500,000,000,000,000,000,000,000` Wei or `0x000080d07666e70de169` encoded as a hexadecimal little endian value. When properly padded to fit into the SCALE encoded storage value, it becomes `69e10de76676d08000000000000000000`, such that the table now looks like:
```text
0x460c0000 // nonce (u32): 3,142
02000000 // consumers (u32): 2
01000000 // providers (u32): 1
06000000 // sufficients (u32): 6
69e10de76676d08000000000000000000
// free (u128): 500,000,000,000,000,000,000,000
40a556b0e032de1200000000000000000
// reserved (u128): 348,052,500,000,000,000,000
4083a09e15c74c1b01000000000000000
// frozen (u128): 20,413,910,106,633,175,872
00000000000000000000000000000080
// flags (u128): 170,141,183,460,469,231,731,687,303,715,884,105,728
```
Therefore, the SCALE encoded override value is as follows:
```text
0x460c000002000000010000000600000069e10de76676d0800000000000000000040a556b0e032de12000000000000000004083a09e15c74c1b0100000000000000000000000000000000000000000000080
```
You can now specify the SCALE encoded override value in your `state-overrides.json` file as follows:
```json
[
{
"pallet": "System",
"storage": "Account",
"key": "0x3b939fead1557c741ff06492fd0127bd287a421e",
"value": "0x460c000002000000010000000600000069e10de76676d0800000000000000000040a556b0e032de12000000000000000004083a09e15c74c1b0100000000000000000000000000000000000000000000080"
}
]
```
To run lazy loading with the balance state override, you can use the following command:
```bash
--lazy-loading-remote-rpc 'INSERT_RPC_URL' --lazy-loading-state-overrides ./state-overrides.json
```
#### Override an ERC-20 Token Balance
To override an ERC-20 token balance, identify the storage slot in the EVM’s AccountStorages where the `balanceOf` data for the given token contract and account is stored. This storage slot is determined by the token contract’s H160 address and the corresponding H256 storage key. Once you have this slot, specify the new balance value in the `state-overrides.json` file to implement the override.
In the example below, we override the token balance of the [Wormhole USDC Contract (`0x931715FEE2d06333043d11F658C8CE934aC61D0c`)](https://moonscan.io/address/0x931715FEE2d06333043d11F658C8CE934aC61D0c){target=_blank} for the account `0x3b939fead1557c741ff06492fd0127bd287a421e` to $5,000 USDC. Since Wormhole USDC uses 6 decimal places, $5,000 corresponds to `5000000000` in integer form, which is `0x12a05f200` in hexadecimal.
```json
[
{
"pallet": "EVM",
"storage": "AccountStorages",
"key": [
"0x931715FEE2d06333043d11F658C8CE934aC61D0c",
"0x8c9902c0f94ae586c91ba539eb52087d3dd1578da91158308d79ff24a8d4f342"
],
"value": "0x000000000000000000000000000000000000000000000000000000012a05f200"
}
]
```
You can calculate the exact storage slot to override for your own account with the following script:
```js
import { ethers } from 'ethers';
function getBalanceSlot(accountAddress) {
// Convert address to bytes32 and normalize
const addr = ethers.zeroPadValue(accountAddress, 32);
// CAUTION! The storage slot used here is 5, which
// is specific to Wormhole contracts
// The storage slot index for other tokens may vary
const packedData = ethers.concat([
addr,
ethers.zeroPadValue(ethers.toBeHex(5), 32),
]);
// Calculate keccak256
return ethers.keccak256(packedData);
}
// Example usage
const address = 'INSERT_ADDRESS';
console.log(getBalanceSlot(address));
```
You can apply the same process for other ERC-20 token contracts. The following sections demonstrate overrides for the `0x3B939FeaD1557C741Ff06492FD0127bd287A421e` account with various ERC-20 tokens. Remember to update the H160 token contract address whenever you switch to a different token. Also, you will need to recalculate the H256 storage slot for each distinct account whose balance you want to override.
??? code "Example: Override Wormhole BTC Token Balance"
```json
[
{
"pallet": "EVM",
"storage": "AccountStorages",
"key": [
"0xE57eBd2d67B462E9926e04a8e33f01cD0D64346D",
"0x8c9902c0f94ae586c91ba539eb52087d3dd1578da91158308d79ff24a8d4f342"
],
"value": "0x000000000000000000000000000000000000000000000000000000012a05f200"
}
]
```
??? code "Example: Override Wormhole ETH Token Balance"
```json
[
{
"pallet": "EVM",
"storage": "AccountStorages",
"key": [
"0xab3f0245B83feB11d15AAffeFD7AD465a59817eD",
"0x8c9902c0f94ae586c91ba539eb52087d3dd1578da91158308d79ff24a8d4f342"
],
"value": "0x000000000000000000000000000000000000000000000000000000012a05f200"
}
]
```
??? code "Example: Override WELL Token Balance"
Because the [WELL token](https://moonbeam.moonscan.io/token/0x511ab53f793683763e5a8829738301368a2411e3){target=_blank} does not use a proxy implementation contract, the storage slot calculation differs. Instead of slot `5`, the balance mapping resides at slot `1`. You can determine the exact storage slot to override the WELL token balance for your own account using the following script:
```js
import { ethers } from 'ethers';
function getBalanceSlot(accountAddress) {
// Convert address to bytes32 and normalize
const addr = ethers.zeroPadValue(accountAddress, 32);
// Caution! The storage slot index used here is 1
// The storage slot index for other tokens may vary
const packedData = ethers.concat([
addr,
ethers.zeroPadValue(ethers.toBeHex(1), 32),
]);
// Calculate keccak256
return ethers.keccak256(packedData);
}
// Example usage
const address = 'INSERT_ADDRESS';
console.log(getBalanceSlot(address));
```
Thus, the storage override would be:
```json
[
{
"pallet": "EVM",
"storage": "AccountStorages",
"key": [
"0x511aB53F793683763E5a8829738301368a2411E3",
"0x728d3daf4878939a6bb58cbc263f39655bb57ea15db7daa0b306f3bf2c3f1227"
],
"value": "0x000000000000000000000000000000000000000000000000000000012a05f200"
}
]
```
## Tracing RPC Endpoint Providers {: #tracing-providers }
Tracing RPC endpoints allow you to access non-standard RPC methods, such as those that belong to Geth's `debug` and `txpool` APIs and OpenEthereum's `trace` module. To see a list of the supported non-standard RPC methods on Moonbeam for debugging and tracing, please refer to the [Debug API & Trace Module](/builders/ethereum/json-rpc/debug-trace/){target=_blank} guide.
The following providers provide tracing RPC endpoints:
- [OnFinality](#onfinality-tracing)
### OnFinality {: #onfinality-tracing }
[OnFinality](https://onfinality.io){target=_blank}'s Trace API can be used to quickly get started tracing and debugging transactions on Moonbeam and Moonriver. It is only available to users on their [Growth and Ultimate plans](https://onfinality.io/pricing){target=_blank}.
To use the Trace API, you simply call the trace method of your choice from your [private RPC endpoint](#onfinality). For a list of the supported networks and trace methods, please check out [OnFinality's Trace API documentation](https://documentation.onfinality.io/support/trace-api#TraceAPI-SupportedNetworks){target=_blank}.
Please note that if you are tracing historic blocks, it is recommended to use your own dedicated trace node to backfill any data, and then once you're caught up, you can switch to using the Trace API. You can check out the [How to Deploy a Trace Node for Moonbeam on OnFinality](https://onfinality.medium.com/how-to-deploy-a-trace-node-for-moonbeam-on-onfinality-85683181d290){target=-_blank} post for more information on how to spin up your own dedicated trace node.
--- END CONTENT ---