• ABOUT

  • WHITEPAPER

  • DOCS

  • DISCORD

  • WALLET

  • EXPLORE

The V439 Upgrade

Conviction for Contracts · July 2026

Introduction

Spec 439brings the chain's stake-lock and miner-conviction system to EVM after v438. Contracts can lock existing alpha, direct conviction to a hotkey, move that lock deliberately, choose perpetual or decaying behavior, and read current coldkey or aggregate hotkey state without reconstructing runtime storage. Subnet owners also gain contract-facing control over whether owner-cut emission is locked automatically.

This is an interface release: it exposes the runtime's existing lock model through the canonical Solidity interfaces and Python SDK ABIs. The important semantics stay on-chain — time-aware decay, conviction maturity, transfer policy, authorization, and cleanup — while contracts get bounded calls with explicit gas accounting.

Lock alpha, build conviction

lockStake turns part of the caller's existing alpha on a subnet into a subnet-wide unstaking floor. It does not move the stake and the locked alpha can live across several staking positions; the supplied hotkey is the target that receives conviction. One coldkey has one lock target per subnet. Repeating the call against that target tops the lock up; changing the target requires moveLock.

IStaking staking = IStaking(0x0000000000000000000000000000000000000805);

staking.lockStake(hotkey, 25_000_000_000, netuid);
staking.setPerpetualLock(netuid, true);

// Resume normal lock decay; there is no separate direct-unlock call.
staking.setPerpetualLock(netuid, false);
EXISTING α STAKECOLDKEYLOCKSUBNET-WIDE FLOORLOCKED MASS→ HOTKEY CONVICTIONPERPETUAL MODEMASS STAYS LOCKEDCONVICTION → MASSDEFAULT · DECAYINGMASS RETURNS OVER TIMECONVICTION ROLLS FORWARDAVAILABLE TO UNSTAKENO DIRECT UNLOCK CALLDISABLE PERPETUAL MODE TO RESUME DECAY

Locks decay by default. Perpetual mode keeps the locked mass fixed while conviction matures; disabling it returns the lock to the runtime's ordinary decay curve.

A move preserves the current rolled locked mass. Conviction is preserved when the source and destination hotkeys share an owner; moving to a differently owned hotkey resets conviction, so an established signal cannot be sold across owner boundaries. The global unlock and maturity timescales are available through getLockRates().

Current state, not stale rows

Lock storage is lazy: it advances when touched rather than writing every block. The new views therefore roll state forward in memory before returning it. getColdkeyLockreturns a coldkey's target hotkey, current locked mass, exact conviction, and perpetual flag. getHotkeyLock combines the relevant perpetual and decaying aggregate buckets; for the subnet owner hotkey it also includes the owner-specific buckets.

EVM CONTRACTSTATICCALLSTAKING V2 · 0x…0805ROLL TO CURRENT BLOCKCHARGE BOUNDED READSRETURN EXACT Q64.64ONE COLDKEYLOCK + TARGETHOTKEY AGGREGATE≤ 64 HOTKEYSORDER PRESERVEDEXPIRED STALE ROWS REPORT exists = false · VIEWS DO NOT MUTATE STORAGE

Every response describes the current block. A fully expired lock reportsexists = false even if a stale storage row has not yet been cleaned up.

Contracts that compare candidates can use getHotkeyConvictions(netuid, hotkeys). The input is capped at 64 distinct hotkeys, results stay aligned with the supplied order, and each conviction is returned as exact unsigned Q64.64 bits. Divide by 2^64 to express it in alpha rao. Duplicate candidates are rejected, and gas grows with the bounded candidate list rather than an unbounded metagraph scan.

Locked alpha moves only by consent

Stake transfers and coldkey swaps can carry a proportional share of locked mass and conviction. Receiving coldkeys reject locked alpha by default, preventing an account from being handed stake it cannot immediately unstake. A recipient opts in with setRejectLockedAlpha(false); contracts can inspect the policy first with getRejectLockedAlpha(coldkey).

Recipient policyUnlocked alphaLocked alpha
Default: rejectAcceptedRejected
Opted inAcceptedAccepted with proportional lock state

The policy belongs to the receiving coldkey, not the sending contract. Integrators should treat a rejection as a consent boundary and ask the recipient to opt in rather than retrying through a different transfer path.

Owner cut can compound into conviction

The subnet precompile at 0x…0803 adds getOwnerCutAutoLockEnabled and setOwnerCutAutoLockEnabled. Auto-locking is off by default. When enabled, new owner-cut emission is added to the subnet owner coldkey's lock: an existing lock keeps its current target; otherwise the subnet owner hotkey becomes the target. The setter preserves the runtime's existing root-or-subnet-owner authorization.

ISubnet subnet = ISubnet(0x0000000000000000000000000000000000000803);

if (!subnet.getOwnerCutAutoLockEnabled(netuid)) {
    subnet.setOwnerCutAutoLockEnabled(netuid, true);
}

This is an opt-in compounding policy, not a change to owner-cut distribution. Subnets that leave the flag false behave exactly as before.

Contract surface

MethodPurpose
lockStakeLock existing subnet alpha and target a hotkey
moveLockMove the lock target with owner-aware conviction handling
setPerpetualLockSwitch between fixed-mass and decaying lock modes
getColdkeyLock / getHotkeyLockRead rolled individual or aggregate lock state
getHotkeyConvictionsRead exact conviction for up to 64 distinct hotkeys
setRejectLockedAlphaControl whether the caller accepts transferred locked alpha
setOwnerCutAutoLockEnabledOpt subnet owner-cut emission into automatic locking

The canonical stakingV2.abi and subnet.abi, their Solidity interfaces, and the Python SDK copies are synchronized in the release. Numeric inputs are range-checked before runtime dispatch, and state-changing calls execute as the precompile's mapped caller account.

What to do

  • Node operators: wait for the on-chain spec_version to move to 439, then update to the matching release.
  • EVM integrators: refresh both canonical ABIs before using the new selectors; the staking methods live on V2 at 0x…0805.
  • Contract developers: decode conviction as unsigned Q64.64, treat query results as already rolled to the current block, and keep conviction batches distinct and at or below 64 hotkeys.
  • Transfer applications:check the destination's locked-alpha policy before moving a position that may carry a lock.
  • Subnet owners: owner-cut auto-lock remains disabled until an owner or root enables it explicitly.

Signers: after the release train proposes, use btcli upgrade sign --url <v439 release URL> -w <wallet>.

Read the staking V2 interface