Guides
Conviction locks
Lock alpha on a subnet, accrue conviction toward a hotkey, and understand the path to subnet ownership — with a worked example on Subnet 7.
Conviction is time-weighted commitment: when you lock-stake
alpha on a subnet, the locked amount accrues conviction toward the lock's
target hotkey. Conviction is not spendable stake — it is a score the chain uses
to recognize long-horizon alignment, including the automatic subnet ownership
transfer when enough aggregate conviction exists.
This guide walks through a fictional Subnet 7 ("Atlas") with three
stakers. The numbers are round teaching examples, not live chain state — always
read real values with subnet-convictions
before acting.
What locking does
A lock is a floor on unstaking, not a separate bucket:
- Your coldkey's total staked alpha on the subnet must stay at or above the locked mass. Anything above remains freely unstakable.
- Locked alpha keeps earning validator dividends and emissions — locking changes liquidity, not rewards.
- Conviction is credited to the hotkey you choose at lock time (often your
validator). Stake and conviction hotkeys can differ, but repeat
lock-stakecalls must target the same hotkey.
One lock per coldkey per subnet. Top-ups add mass; conviction continues from its current value.
Example subnet: Atlas (netuid 7)
| Field | Value | Meaning |
|---|---|---|
SubnetAlphaOut | 8,000,000 α | Outstanding alpha on the subnet |
| Ownership threshold | 800,000 α | 10% of alpha out — aggregate conviction gate |
| Subnet age | > 1 year | Required before ownership can transfer |
| Alice (owner) | 250,000 α locked | Perpetual lock on owner hotkey — conviction = mass |
| Bob (validator) | 600,000 α locked | Perpetual lock toward his validator hotkey |
| Carol (staker) | 200,000 α locked | Decaying lock (default) toward a validator |
Fictional numbers for illustration. Three coldkeys lock toward different hotkeys; total conviction must reach 10% of SubnetAlphaOut before ownership can transfer.
SubnetAlphaOut
8.00M α
10% threshold
800.0k α
Subnet age
434.7 d
Ownership gate
Closed
Alice (owner hotkey)
250.0k α
Owner locks: conviction = locked mass instantly
Bob (validator)
208.9k α
Perpetual lock
Carol (staker)
55.8k α
Decaying — mass frees over time
Total / threshold
514.6k α / 800.0k α
64.3% of gate
Drag elapsed time forward: Bob's perpetual conviction climbs toward 600k α. Carol's decaying conviction rises then falls as her locked mass frees. When total conviction crosses 800k α and the subnet is old enough, the highest-conviction hotkey becomes the new owner.
Perpetual vs decaying
New locks are decaying by default. Opt into perpetual with
set-perpetual-lock.
| Mode | Locked mass | Conviction |
|---|---|---|
| Perpetual | Fixed | Approaches mass: c = m − (m − c₀)·e^(−Δt/τ) |
| Decaying | Exponential decay on UnlockRate | Integral of decaying mass — peaks, then falls |
On mainnet today MaturityRate is 311,622 blocks (~43 days) and
UnlockRate is 934,866 blocks (~130 days). Both are governance-set
storage values — read them live before planning, do not hardcode them.
Same 500k α lock on a subnet hotkey. Perpetual: mass stays, conviction approaches mass. Decaying: mass frees on UnlockRate; conviction peaks then falls.
Perpetual at 1τ
316.1k α
63.2% of mass
Decaying peak conviction
183.9k α
Rises while mass decays, then falls
Locked mass (start)
500.0k α
Subnet ownership via conviction
After each epoch, the chain runs change_subnet_owner_if_needed when all of
these hold:
- Subnet age ≥ ONE_YEAR (2,629,800 blocks from registration).
- Total aggregate conviction ≥ 10% of
SubnetAlphaOut. - A hotkey with the highest rolled aggregate conviction resolves to a real coldkey owner (not the default account).
The winning hotkey becomes SubnetOwnerHotkey; its coldkey becomes
SubnetOwner. If the leader already owns the subnet, nothing changes.
This is not the same as the per-hotkey projection in
subnet-convictions — that API estimates when
one hotkey might reach 10% of alpha out; ownership requires aggregate
conviction across all lockers.
Lock a position on a real subnet
Replace netuid 7 with your target subnet:
# Inspect existing locks and conviction leaderboard
btcli query subnet-convictions --netuid 7 --json
btcli query hotkey-conviction --hotkey <ss58> --netuid 7 --json
btcli query coldkey-lock --coldkey <ss58> --netuid 7 --json
# Lock 1,000 alpha toward a validator hotkey (dry-run first)
btcli tx lock-stake --netuid 7 --amount-alpha 1000 --dry-run -w my_coldkey
btcli tx lock-stake --netuid 7 --amount-alpha 1000 -w my_coldkey
# Switch to perpetual mode (irreversible public signal when switching to decaying)
btcli tx set-perpetual-lock --netuid 7 --enabled -w my_coldkeyThe same flow in Python — lock, opt into perpetual, then read conviction back:
await client.execute(bt.LockStake(netuid=7, hotkey_ss58="5F...", amount_alpha=1000), wallet)
await client.execute(bt.SetPerpetualLock(netuid=7, enabled=True), wallet)
lock = await client.locks.coldkey_lock(coldkey_ss58="5C...", netuid=7)
conviction = await client.locks.hotkey_conviction(hotkey_ss58="5F...", netuid=7)Transferring locked stake
A lock is a coldkey-wide floor, not a hold on one validator position. You
can lock conviction to the owner hotkey while the alpha sits on a different
validator hotkey. That split is supported — and it is the usual source of
LockHotkeyMismatch / "not enough
stake" confusion when transferring.
Check free vs locked first:
btcli stake list # shows locked · free · lock → <hotkey>
btcli lock show --netuid <n>
btcli query coldkey-lock --coldkey <ss58> --netuid <n>Then pick a path:
| Situation | What to do |
|---|---|
| Amount ≤ free (unlocked) α | transfer-stake from the hotkey that holds the stake (often the validator). Lock mass does not move. |
| Amount > free (pulls locked α) | Lock mass follows the transfer. The landing hotkey must match the receiver's existing lock hotkey, or the call fails with LockHotkeyMismatch. |
| Stake on vali A, lock on owner B, transferring locked α | Do not consolidate onto B first. Use transfer-stake with --hotkey A --destination-hotkey <receiver-lock-hotkey> (dispatches transfer_stake_and_hotkey). |
| Origin hotkey holds less than the amount | Fails with NotEnoughStakeToWithdraw even if the coldkey has enough total α elsewhere — stake is pulled from one hotkey. |
Worked example — sender has 2,000 free + 1,000 locked, stake on vali V,
lock (and receiver's lock) on owner O:
# Wrong: lands on V; receiver locks to O → LockHotkeyMismatch
btcli stake transfer \
--dest-coldkey <receiver> --hotkey V \
--origin-netuid 122 --dest-netuid 122 --amount-alpha 3000
# Wrong: pulls from O, but stake still sits on V → NotEnoughStakeToWithdraw
btcli stake transfer \
--dest-coldkey <receiver> --hotkey O \
--origin-netuid 122 --dest-netuid 122 --amount-alpha 3000
# Right: pull from V, land on O (receiver's lock hotkey)
btcli stake transfer \
--dest-coldkey <receiver> --hotkey V --destination-hotkey O \
--origin-netuid 122 --dest-netuid 122 --amount-alpha 3000After a successful transfer, the receiver's lock mass increases on O
while their stake can still be moved to another validator afterward —
lock target and stake hotkey may differ on both sides. That is not the lock
"unlocking"; it is the floor moving with the coldkey.
Recipient coldkeys reject locked α by default — they must opt in via
SubtensorModule.set_reject_locked_alpha(false) before accepting a transfer
that moves lock mass
(AccountRejectsLockedAlpha).
Rules worth remembering
move-lockto another hotkey owned by a different coldkey resets conviction to zero; same-owner moves preserve it.- Subnet deregistration deletes lock records — conviction is lost even if stake is paid out through the pool.
- A coldkey swap fails if the destination has active locked mass on any subnet.
- Transferring more than free α moves lock mass with the stake; see Transferring locked stake.
For staking mechanics beyond locks, see the Staking guide.