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.

View as Markdown

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-stake calls 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)

FieldValueMeaning
SubnetAlphaOut8,000,000 αOutstanding alpha on the subnet
Ownership threshold800,000 α10% of alpha out — aggregate conviction gate
Subnet age> 1 yearRequired before ownership can transfer
Alice (owner)250,000 α lockedPerpetual lock on owner hotkey — conviction = mass
Bob (validator)600,000 α lockedPerpetual lock toward his validator hotkey
Carol (staker)200,000 α lockedDecaying lock (default) toward a validator
Example: Subnet 7 (Atlas)

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

Carol's mode (set-perpetual-lock)
55.6 d
600.0k α
200.0k α

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.

ModeLocked massConviction
PerpetualFixedApproaches mass: c = m − (m − c₀)·e^(−Δt/τ)
DecayingExponential decay on UnlockRateIntegral 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.

Perpetual vs decaying lock

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 α

500.0k α
194.8 d

Subnet ownership via conviction

After each epoch, the chain runs change_subnet_owner_if_needed when all of these hold:

  1. Subnet age ≥ ONE_YEAR (2,629,800 blocks from registration).
  2. Total aggregate conviction ≥ 10% of SubnetAlphaOut.
  3. 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_coldkey

The 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:

SituationWhat 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 amountFails 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 3000

After 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-lock to 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.