Multisig docs
Look up any call, event, or storage item with code examples. Runtime v472 · Block #9,197,056
Developer documentation for the Multisig pallet of the Subtensor blockchain, part of the Bittensor decentralized AI network. This page is designed for developers integrating with the chain: look up any call, event, or storage item, copy code examples in TypeScript, Python, or Rust, and filter by your role. For in-depth explanations, version history, and relationships between items, see the Reference section.
Multisig
Immediately dispatch a multi-signature call using a single approval from the caller.
Calls 5
Immediately dispatch a call using a single approval from the caller.
Parameters
| Name | Type | Format | Description |
|---|---|---|---|
other_signatories | Vec<AccountId> | Array of SS58 Address | other_signatories: list of Account address (32 bytes, SS58-encoded) |
call | RuntimeCall | — | call (RuntimeCall) |
// ----------------------------------------------------------------------
// HEADS UP: 1 arg below has a complex type with no usable default.
// Look for `undefined as any` and replace it with real value
// before running — the snippet compiles, but will fail at runtime as-is.
// ----------------------------------------------------------------------
import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Build as_multi_threshold_1 call (typed, named args)
const other_signatories = [] as [];
const call = undefined as any /* RuntimeCall — replace with real value */;
const tx = api.tx.Multisig.as_multi_threshold_1({
other_signatories,
call,
});Register approval for a dispatch, executing if threshold is reached.
Parameters
| Name | Type | Format | Description |
|---|---|---|---|
threshold | u16 | Integer (0-65535) | threshold (u16) |
other_signatories | Vec<AccountId> | Array of SS58 Address | other_signatories: list of Account address (32 bytes, SS58-encoded) |
maybe_timepoint | Option | — | maybe_timepoint (Option) |
call | RuntimeCall | — | call (RuntimeCall) |
max_weight | Weight | Execution Weight | max_weight: Substrate dispatch weight (computational cost) |
// ----------------------------------------------------------------------
// HEADS UP: 2 args below have a complex type with no usable default.
// Look for `undefined as any` and replace them with real values
// before running — the snippet compiles, but will fail at runtime as-is.
// ----------------------------------------------------------------------
import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Build as_multi call (typed, named args)
const threshold = 0;
const other_signatories = [] as [];
const timepoint = undefined;
const call = undefined as any /* RuntimeCall — replace with real value */;
const max_weight = undefined as any /* Weight — replace with real value */;
const tx = api.tx.Multisig.as_multi({
threshold,
other_signatories,
maybe_timepoint: timepoint,
call,
max_weight,
});Register approval without providing full call data (hash only).
Parameters
| Name | Type | Format | Description |
|---|---|---|---|
threshold | u16 | Integer (0-65535) | threshold (u16) |
other_signatories | Vec<AccountId> | Array of SS58 Address | other_signatories: list of Account address (32 bytes, SS58-encoded) |
maybe_timepoint | Option | — | maybe_timepoint (Option) |
call_hash | [u8; 32] | — | call_hash ([u8; 32]) |
max_weight | Weight | Execution Weight | max_weight: Substrate dispatch weight (computational cost) |
// ----------------------------------------------------------------------
// HEADS UP: 1 arg below has a complex type with no usable default.
// Look for `undefined as any` and replace it with real value
// before running — the snippet compiles, but will fail at runtime as-is.
// ----------------------------------------------------------------------
import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Build approve_as_multi call (typed, named args)
const threshold = 0;
const other_signatories = [] as [];
const timepoint = undefined;
const call_hash = "0x0000000000000000000000000000000000000000000000000000000000000000";
const max_weight = undefined as any /* Weight — replace with real value */;
const tx = api.tx.Multisig.approve_as_multi({
threshold,
other_signatories,
maybe_timepoint: timepoint,
call_hash,
max_weight,
});Cancel a pending multisig operation and reclaim the deposit.
Parameters
| Name | Type | Format | Description |
|---|---|---|---|
threshold | u16 | Integer (0-65535) | threshold (u16) |
other_signatories | Vec<AccountId> | Array of SS58 Address | other_signatories: list of Account address (32 bytes, SS58-encoded) |
timepoint | Timepoint | — | timepoint (Timepoint) |
call_hash | [u8; 32] | — | call_hash ([u8; 32]) |
// ----------------------------------------------------------------------
// HEADS UP: 1 arg below has a complex type with no usable default.
// Look for `undefined as any` and replace it with real value
// before running — the snippet compiles, but will fail at runtime as-is.
// ----------------------------------------------------------------------
import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Build cancel_as_multi call (typed, named args)
const threshold = 0;
const other_signatories = [] as [];
const timepoint = undefined as any /* Timepoint — replace with real value */;
const call_hash = "0x0000000000000000000000000000000000000000000000000000000000000000";
const tx = api.tx.Multisig.cancel_as_multi({
threshold,
other_signatories,
timepoint,
call_hash,
});Update the deposit for an existing multisig operation.
Parameters
| Name | Type | Format | Description |
|---|---|---|---|
threshold | u16 | Integer (0-65535) | threshold (u16) |
other_signatories | Vec<AccountId> | Array of SS58 Address | other_signatories: list of Account address (32 bytes, SS58-encoded) |
call_hash | [u8; 32] | — | call_hash ([u8; 32]) |
import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Build poke_deposit call (typed, named args)
const threshold = 0;
const other_signatories = [] as [];
const call_hash = "0x0000000000000000000000000000000000000000000000000000000000000000";
const tx = api.tx.Multisig.poke_deposit({
threshold,
other_signatories,
call_hash,
});Events 5
Emitted when a new multisig operation is initiated.
When it fires
- Caller is one of the signatories
- This is the first approval for this call
- Threshold is 2 or greater
Fields
| Name | Type | Format | Description |
|---|---|---|---|
approving | AccountId | SS58 Address | Account that initiated the multisig operation |
multisig_account | AccountId | SS58 Address | The derived multisig account address |
call_hash | [u8; 32] | — | Blake2-256 hash of the call to be executed |
import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Subscribe to NewMultisig events
client.finalizedBlock$.subscribe(async (block) => {
const events = await api.event.Multisig.NewMultisig.get(block.hash);
for (const evt of events) {
console.log("NewMultisig:", evt.payload);
}
});Emitted when a signatory approves a pending multisig operation.
When it fires
- Multisig operation exists
- Caller is an authorized signatory
- Caller hasn't already approved
Fields
| Name | Type | Format | Description |
|---|---|---|---|
approving | AccountId | SS58 Address | Account that approved the operation |
timepoint | Timepoint | — | Block height and extrinsic index when operation was created |
multisig_account | AccountId | SS58 Address | The derived multisig account address |
call_hash | [u8; 32] | — | Blake2-256 hash of the call to be executed |
import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Subscribe to MultisigApproval events
client.finalizedBlock$.subscribe(async (block) => {
const events = await api.event.Multisig.MultisigApproval.get(block.hash);
for (const evt of events) {
console.log("MultisigApproval:", evt.payload);
}
});Emitted when a multisig operation is executed after reaching threshold.
When it fires
- Required threshold of approvals reached
- Final approval provided with full call data
Fields
| Name | Type | Format | Description |
|---|---|---|---|
approving | AccountId | SS58 Address | Account that provided the final approval |
timepoint | Timepoint | — | Block height and extrinsic index when operation was created |
multisig_account | AccountId | SS58 Address | The derived multisig account address |
call_hash | [u8; 32] | — | Blake2-256 hash of the executed call |
result | Result | — | Result of the call execution (Ok or Err with dispatch error) |
import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Subscribe to MultisigExecuted events
client.finalizedBlock$.subscribe(async (block) => {
const events = await api.event.Multisig.MultisigExecuted.get(block.hash);
for (const evt of events) {
console.log("MultisigExecuted:", evt.payload);
}
});Emitted when a pending multisig operation is cancelled.
When it fires
- Multisig operation exists
- Caller is the original depositor
Fields
| Name | Type | Format | Description |
|---|---|---|---|
cancelling | AccountId | SS58 Address | Account that cancelled the operation |
timepoint | Timepoint | — | Block height and extrinsic index when operation was created |
multisig_account | AccountId | SS58 Address | The derived multisig account address |
call_hash | [u8; 32] | — | Blake2-256 hash of the cancelled call |
import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Subscribe to MultisigCancelled events
client.finalizedBlock$.subscribe(async (block) => {
const events = await api.event.Multisig.MultisigCancelled.get(block.hash);
for (const evt of events) {
console.log("MultisigCancelled:", evt.payload);
}
});Emitted when a multisig deposit is updated after parameter changes.
When it fires
- Multisig operation exists
- Caller is the original depositor
Fields
| Name | Type | Format | Description |
|---|---|---|---|
who | AccountId | SS58 Address | Account whose multisig deposit was adjusted |
call_hash | [u8; 32] | — | Blake2-256 hash of the call held by the multisig |
old_deposit | TaoBalance | — | Previous deposit amount (BalanceOf<T>, RAO) |
new_deposit | TaoBalance | — | New deposit amount after adjustment (BalanceOf<T>, RAO) |
import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Subscribe to DepositPoked events
client.finalizedBlock$.subscribe(async (block) => {
const events = await api.event.Multisig.DepositPoked.get(block.hash);
for (const evt of events) {
console.log("DepositPoked:", evt.payload);
}
});Storage 1
The set of open multisig operations.
Multisig Keys
| Name | Type | Format | Description |
|---|---|---|---|
key1 | AccountId | SS58 Address | — |
key2 | [u8; 32] | — | — |
import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Query Multisigs storage
const key1 = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY";
const key2 = "0x0000000000000000000000000000000000000000000000000000000000000000";
const result = await api.query.Multisig.Multisigs.getValue(key1, key2);
console.log("Multisigs:", result);Constants 3
Base deposit for creating a multisig.
TaoBalance"132000000"import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Query DepositBase constant
const value = await api.constants.Multisig.DepositBase();
console.log("DepositBase:", value);
// Balance: divide by 10^9 for TAO
const tao = value / 1_000_000_000n;Per-signatory deposit factor.
TaoBalance"32000000"import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Query DepositFactor constant
const value = await api.constants.Multisig.DepositFactor();
console.log("DepositFactor:", value);
// Balance: divide by 10^9 for TAO
const tao = value / 1_000_000_000n;Maximum signatories for a multisig.
u32100import { createClient, Binary } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws";
import { sub } from "@polkadot-api/descriptors"; // generated by: npx papi add sub -w wss://entrypoint-finney.opentensor.ai:443
const client = createClient(getWsProvider("wss://entrypoint-finney.opentensor.ai:443"));
const api = client.getTypedApi(sub);
// Query MaxSignatories constant
const value = await api.constants.Multisig.MaxSignatories();
console.log("MaxSignatories:", value);Errors 14
Threshold must be at least 2 for multisig operations.
Common Causes
- Setting threshold to 1 (use regular calls instead)
- Setting threshold to 0
How to Fix
Use threshold of 2 or higher for multisig,For single-signer operations, use regular calls
This signatory has already approved this multisig call.
Common Causes
- Accidentally calling approve_as_multi twice
- Signatory confusion about approval status
How to Fix
Check current approvals before submitting,Wait for other signatories to approve
Threshold of 1 means no additional approvals needed.
Common Causes
- Using approve_as_multi with threshold 1
- Misconfigured multisig
How to Fix
Use as_multi_threshold_1 for single-signer calls,Set threshold to 2 or higher if multisig is intended
Not enough signatories provided for the multisig.
Common Causes
- Signatory list shorter than threshold
- Missing signatories in the list
How to Fix
Provide at least threshold number of signatories,Verify all intended signatories are included
Signatory count exceeds the maximum allowed.
Common Causes
- Adding too many signatories
- Exceeding MaxSignatories constant
How to Fix
Reduce signatory count to MaxSignatories or less,Check MaxSignatories constant for the limit
Signatories must be provided in sorted order.
Common Causes
- Signatory addresses not sorted
- Incorrect ordering of addresses
How to Fix
Sort signatory addresses in ascending order,Use lexicographic sorting on raw bytes
The sender should not be included in the signatories list.
Common Causes
- Including caller's address in signatories
- Confusion about who counts as a signatory
How to Fix
Remove the caller from the signatories list,Caller is implicitly counted as a signatory
No multisig operation found for this call hash.
Common Causes
- Multisig operation was never created
- Wrong call hash provided
- Multisig was already executed or cancelled
How to Fix
Verify the call hash is correct,Check if the multisig was already completed,Create a new multisig operation if needed
Caller is not an owner/signatory of this multisig.
Common Causes
- Wrong account trying to approve/cancel
- Account not in the original signatory list
How to Fix
Use an account that is a signatory,Verify the signatory list matches
A timepoint is required but was not provided.
Common Causes
- Missing timepoint parameter
- Calling approve without previous operation
How to Fix
Provide the timepoint from the original operation,Query Multisigs storage for the correct timepoint
The provided timepoint does not match the stored operation.
Common Causes
- Using timepoint from a different operation
- Timepoint changed due to re-creation
How to Fix
Query the correct timepoint from storage,Use the timepoint from the operation creation
A timepoint was provided when none was expected.
Common Causes
- Providing timepoint for new operation
- Providing timepoint for as_multi_threshold_1
How to Fix
Omit timepoint for the first approval,Check if operation already exists
The maximum weight specified is too low for the call.
Common Causes
- Underestimating call weight
- Weight limits too restrictive
How to Fix
Increase the max_weight parameter,Estimate call weight more accurately
The call data is already stored on-chain.
Common Causes
- Attempting to store call data twice
- Operation already created with store_call=true
How to Fix
Use existing stored call instead,Omit call data and use call hash