Polkadot (DOT) and Kusama (KSM) are built using nearly the same codebase. Kusama is a development environment for teams who want to deploy on Kusama or prepare for deployment on Polkadot.
Polkadot and Kusama Proof-of-Stake ecosystem
Polkadot and Kusama use a Nominated Proof-of-Stake (NPoS) consensus mechanism. The NPoS system requires nominators to bond funds for staking, and then assign that stake to a list of validators who are responsible for minting blocks. Validators must then process transactions for all parachains. They are responsible for continuous good performance which includes remaining online and running complete, up-to-date software.
Rewards
Validators receive DOT or KSM tokens as the block reward. The reward for producing a block is always the same regardless of the total stake. Validators with fewer nominators distribute higher rewards per nominator. This incentivizes smaller groups of nominators per validator. Every 24 hours, an election takes place in which validators are selected to participate in minting blocks in the blockchain. Nominators can list up to 16 validators. Once validators are selected, nominations are active for the following 24 hours.
Polkadot staking on Fireblocks
There are two different account types for managing staked funds: Stash
and Controller
.
- Stash: This account holds funds bonded for staking, but delegates some functions to a Controller account. As a result, Stash keys may be kept in cold wallets that stay offline all the time. You can also designate a Proxy account to vote on governance proposals.
- Controller: This account signals decisions about nominating and validating on behalf of the Stash account. It sets preferences like payout account and commission. For validators, it also sets session keys. It only needs to hold enough funds to pay transaction fees.
The customer's stash account performs staking operations via a staking proxy account managed by the staking provider. The proxy account adds a security layer and enables the staking provider to manage nomination, validation, and governance functions transparently for the customer.
Workspace configuration
To set up Polkadot or Kusama staking from Fireblocks, confirm you have completed all prerequisites for staking. Then configure your workspace using the following settings:
- Create two dedicated vault accounts, each with DOT or KSM wallets.
- The Stash vault account holds the DOT or KSM funds you plan on staking.
- The Controller vault account has permission to assign nominations.
- Deposit the DOT or KSM you would like to stake into the Stash account. As of January 2023, a minimum of 100 DOT is required to begin staking. You can check the current nominator minimum at https://staking.polkadot.network/#/overview
- Deposit at least 25 DOT or about 2 KSM in the Controller account to cover transaction fees.
Staking and unstaking
Staking and unstaking commands are part of the SDK (TypeScript) provided by Fireblocks. This SDK interacts with our API and the Polkadot and Kusama blockchains and should be embedded in your infra flows.
All parameters are defined in the table below.
Staking
Staking on Polkdadot and Kusama requires identifying the staking proxy partner, bonding assets from the stash account, and identifying a controller account and rewards destination.
The addProxy call associates the customer's account ID with the staking partner proxy that manages the validators. The bond() call allocates the funds to be staked. These two calls should be called once per account.
Run these two commands to create a new staking transaction:
addProxy(<controller_account_vault_account_id>, <proxy_dot_address>);
bond(<stash_account_vault_account_id>, <amount_to_stake>, <controller_account_address>
,<reward_destination?>);
To increase your stake of DOT or KSM, run the following command:
bondExtra(<stash_account_vault_account_id>, <amount_to_bond?>);
Note: Increasing the bonded and staked amount requires using bondExtra(). Calling bond() multiple times for the same stash vault account will result in an error.
Unstaking
To unstake an entire stake, run the following commands sequentially:
chill(<controller_account_vault_account_id>);
unbond(<controller_account_vault_account_id>, <amount_to_unbond?>);
You may withdraw funds 28 days (or 7 days on Kusama) after running unbond() by running:
withdrawUnbonded(<controller_account_vault_account_id>);
If you no longer wish to stake DOT or KSM from this account and have withdrawn all funds from your Stash and Controller accounts, you may optionally disconnect your address from the proxy accordingly:
removeProxy(<controller_account_vault_account_id>, <proxy_dot_address>);
Changing the controller address:
setController(<stash_account_vault_account_id>, <controller_address>);
SDK parameters
Parameter | Definition |
controller_account_vault_account_id | Controller account vault ID |
proxy_dot_address | Validator's proxy address from the staking partner |
stash_account_vault_account_id | The Stash account vault ID created in your Fireblocks workspace |
amount_to_stake | Amount to bond & stake in the initial bond call |
controller_account_address | The Controller account blockchain address |
reward_destination (optional) |
Rewards are sent to this account Stash (Default): Deposit rewards into the stash account without increasing the staked amount. Staked: Deposit rewards into the stash account, and automatically increase the amount at stake accordingly. Controller: Deposit rewards into the controller account. Rewards are automatically bonded or staked, and can be transferred freely. |
amount_to_bond | Amount to add when staking additional funds with bondExtra() after an initial bond/stake call |
amount_to_unbond | Amount to unbond so it can become available for withdrawal. The amount should be equal to or less than the total amount bonded in this stash account. |
SDK example
The following code snippet describes how to set up staking calls. The apiKey can be retrieved by following these instructions.
import fs from "fs";
import path from "path";
import { FireblocksSDK } from "fireblocks-sdk";
import { DOTStaker } from "./src/dot-staker";
const apiSecret = fs.readFileSync(path.resolve(__dirname, "./fireblocks_secret.key"), "utf8");
const apiKey = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
const fireblocks = new FireblocksSDK(apiSecret, apiKey);
const dotStaker = new DOTStaker(fireblocks, false);
(async() => {
await dotStaker.addProxy(<controller_vault_account_id>, <proxy_address>);
})().catch(console.log);