Guides/Mining
Registration collateral
Lock a share of the registration price as a bond you earn back by mining; misbehave and it stays frozen.
Subnets can turn part of the registration price into collateral: instead of burning the whole price, the subnet locks a share of it as alpha stake on your hotkey. The lock is released back to you at a fixed rate per alpha of miner incentive you earn — so the only way to recover it is to actually mine. It survives deregistration, is credited when you re-register the same hotkey, and has no other exit: quit for good and the remainder stays frozen on the hotkey indefinitely.
The design in one line: the burn prices the registration event; the collateral prices your behavior after it. A hotkey that mines honestly for its career pays only the burn. A hotkey that registers and never earns — a sybil, a UID squatter, a spam registration — forfeits the lock in practice, because nothing ever releases it. And a hotkey that cheats loses it too: see enforcement below.
Mechanics
Two per-subnet hyperparameters define the whole system:
| — | name | meaning | default |
|---|---|---|---|
p | collateral_lock_share | share of the registration price locked instead of burned | 0 (disabled) |
k | collateral_drain_ratio | alpha released per alpha of miner incentive earned | 1.0 |
With price T (the same floating price described in
registration burn), registration charges:
burned = (1 − p) × T — recycled, sunk
locked collateral = max(0, p × T − standing collateral) — staked to your hotkey, lockedThere is no special first-time case: a fresh hotkey has zero standing
collateral and pays the full p × T; a returning hotkey's existing lock is
valued at the subnet's moving-average price and credited, so it usually pays only the
burned share. This is implemented in
do_register
via
get_collateral_topup_tao
and
pay_registration.
The locked alpha is real stake owned by your coldkey on your hotkey — it
appreciates and depreciates with the subnet's pool like any alpha — but it is
not withdrawable: the unstake guard
(stake_availability)
subtracts it from what your coldkey can remove, and a per-hotkey check
(ensure_hotkey_covers_collateral)
keeps the bond on that hotkey (sibling free stake cannot cover it). If the
subnet dissolves, the lock metadata is cleared after alpha is settled to
coldkey free TAO with everyone else's stake — there is no separate collateral
refund step.
Earning it back
Each tempo, when the chain credits your miner incentive
(distribute_dividends_and_incentives),
it also releases collateral:
released = min(locked − min_locked, k × incentive)(min_locked is your optional self-maintained floor, described below; it is
zero unless you set one, giving the plain min(locked, k × incentive).)
(settle_miner_collateral).
Released collateral simply becomes withdrawable stake — it was your alpha all
along; only the lock flag moves. At k = 1, every alpha you earn frees one
alpha of collateral: a miner who has earned emissions equal to their lock is
fully released. At k = 0.5 you must earn two alpha per alpha released —
subnets use low k to keep miners collateralized longer.
Your k is snapshot at registration into your collateral entry: owner
changes to the drain ratio apply to future registrations, never to your
standing lock.
Voluntary collateral: add_collateral and set_min_collateral
Beyond the registration lock, two miner-initiated calls let a subnet run deposit-style policies (for example, "post X alpha per machine you bring"):
| Call | What it does | Units |
|---|---|---|
add_collateral | Lock more alpha on your own hotkey | TAO-value in, alpha locked |
set_min_collateral | Set a self-maintaining floor under the lock | alpha |
Both require the signing coldkey to own the hotkey. Neither is a subnet hyperparameter: owners publish the required amount off chain (docs, validator code); miners fund and park it; validators enforce by reading the metagraph and refusing to score under-collateralized hotkeys. The full Lium-style pattern is in a GPU marketplace with per-machine deposits below.
add_collateral
add_collateral tops up the hotkey's locked
collateral by about the TAO-value you pass. Funding order:
- Free stake first. Alpha already staked on that
(hotkey, coldkey)position, above what is already locked, is reclassified as collateral at the subnet's moving price. No swap, no slip. - Buy the shortfall. Only the remainder is bought with coldkey TAO
(keep-alive fill-or-kill: a partial buy that would leave you under ED
fails with
NotEnoughBalanceToStake). The buy is priced likeadd_stake_limit— fill-or-kill against spot × (1 +--rate-tolerance, default 5%) — and the CLI / SDK always submit it MEV-shielded (--no-mev-shieldis refused). Registration collateral buys use the same 5% runtime bound when a lock share is due.
The new lock joins the same entry as registration collateral: same drain
ratio snapshot (or the subnet's current k if this is your first lock on
the hotkey), same persistence across deregistration, same credit on
re-registration. There is still no withdrawal path other than earned
incentive.
# Prefer the collateral subcommand; btcli tx add-collateral is equivalent.
btcli collateral add --netuid 51 --amount-tao 100 -w my_coldkey -H my_hotkey
btcli collateral add --netuid 51 --amount-tao all -w my_coldkey -H my_hotkey --dry-run# execute() redirects AddCollateral to submit_shielded automatically.
await client.execute(
bt.AddCollateral(netuid=51, amount_tao=100, hotkey_ss58=wallet.hotkey_address),
wallet,
)Emits CollateralLocked { locked, total_locked } for the amount just added.
Fails with AmountTooLow if the TAO-value converts to zero alpha,
NonAssociatedColdKey if you don't own the hotkey, StakeUnavailable if
free stake moved out from under the preflight, SlippageTooHigh if the
shortfall buy would clear above the limit, or the usual staking errors
when buying the shortfall.
set_min_collateral
set_min_collateral sets a floor
(min_locked) the lock self-maintains around. It does not move stake by
itself:
released each tempo = min(locked − min_locked, k × incentive) # never below the floor
while locked < min_locked: earned incentive is captured into the lock until the floor is metWithout a floor, tracking a validator-published requirement means re-running
add_collateral every tempo as the drain releases headroom. With one, the
chain parks the lock and tops it up from incentive when it dips. Zero
clears the floor and restores pure drain behavior (the exit step in the
Lium wind-down).
btcli collateral set-min --netuid 51 --min-alpha 100 -w my_coldkey -H my_hotkey
btcli collateral set-min --netuid 51 --min-alpha 0 -w my_coldkey -H my_hotkey # clearawait client.execute(
bt.SetMinCollateral(netuid=51, min_alpha=100, hotkey_ss58=wallet.hotkey_address),
wallet,
)Emits MinCollateralSet { min_locked }. Raising the floor above your current
lock needs no fresh capital: the shortfall fills from future incentive. But
validators see your actual collateral_locked, not your floor, so fund
with add_collateral when coverage must hold now (before the next scored
tempos).
Typical sequence for a deposit policy:
btcli collateral add --netuid 51 --amount-tao 100 -w my_coldkey -H my_hotkey
btcli collateral set-min --netuid 51 --min-alpha 100 -w my_coldkey -H my_hotkey
btcli collateral show --netuid 51 -H my_hotkey
btcli collateral list --netuid 51 # what validators readawait client.execute(bt.AddCollateral(netuid=51, amount_tao=100), wallet)
await client.execute(bt.SetMinCollateral(netuid=51, min_alpha=100), wallet)
state = await client.collateral.miner_collateral(
netuid=51, hotkey_ss58=wallet.hotkey_address,
)
# state["locked_alpha"], ["min_locked_alpha"], ["earned_alpha"], ["headroom_alpha"], ...Query the same fields on-chain with
miner-collateral (one position) or
subnet-collateral (every entry on the
subnet, including dormant bonds). Registered neurons also expose
collateral_locked, collateral_min, and collateral_earned on the
metagraph.
The whole lifecycle in one picture. Drag the sliders for lock share, drain
ratio, floor, and a mid-career add_collateral, and switch to the blacklisted
scenario to see stranding:
Registration splits the price: (1 − p) burned, p locked to the hotkey. Each scored tempo releases k × incentive above the floor; add_collateral tops the lock up mid-career, and set_min_collateral parks it at a floor that earned incentive refills. If validators blacklist the hotkey (off chain, by not scoring it), incentive stops and the remainder strands.
At registration
2.0 α burned + 8.0 α locked
p = 80% of a 10 α price
Fully released after
beyond window
bond ÷ (k × incentive) at k = 0.5
Still locked at window end
2.00 α
keeps draining as incentive is earned
Deregistration and re-registration
Being pruned does not touch collateral. The lock freezes in place, attached
to (netuid, hotkey), and waits. When you re-register the same hotkey, it is
credited against the current requirement — the single registration formula
above handles it — so a pruned miner returns for roughly the burned share
alone. If the price or lock share rose since, you top up the difference; if
your standing lock exceeds the current requirement, you pay only the burn and
the excess keeps draining as you earn.
There is deliberately no withdrawal path. Collateral converts back to
withdrawable stake only through earned incentive. Abandoning a hotkey
strands whatever is still locked (a standing incentive to come back and mine
it out); swap-hotkey moves the lock to the new
hotkey along with everything else
(swap_miner_collateral).
Enforcement: the off-chain blacklist
The chain never adjudicates miner behavior — there is no ban extrinsic. The teeth are simpler: validators score miners off-chain, and a validator that concludes a hotkey is cheating simply stops evaluating it. Zero incentive means zero collateral release, forever. The lock strands — economically confiscated, without any judicial machinery:
- It is stake-weighted by construction: one validator refusing to score you reduces your incentive by its weight in consensus; a supermajority blacklist freezes your collateral outright.
- It is reversible: if validators resume evaluating (wrong call, or the miner reformed), the lock resumes draining.
- Nobody profits from it: frozen collateral pays no one, so there is no bounty for banning.
The residual escape — rotating to a fresh hotkey — costs the full
registration price including a fresh full lock. Hotkey swap is refused while
standing collateral remains and the hotkey lacks validator permit on that
subnet (permitted validators on collateral-enabled subnets can still rotate).
The system's invariant is exactly that: forgetting is never cheaper than T.
Note for validator authors: this only holds if your scoring state is keyed by hotkey (not UID) and persists across the miner's deregistrations. UIDs are recycled slots; a miner must not be able to launder a bad track record by cycling registration. Treat scoring gaps conservatively — absence should never improve a score.
Worked examples
A trading subnet deters tail-risk farming
Netuid 42 rewards trading signals by Sortino ratio. The metric is blind to strategies that sell tail risk: a martingale posts a top-percentile score for months, farms emissions, then blows up. Under pure burn (price τ10), a farmer who collects τ80 of emissions before the blow-up nets τ70 per cycle and repeats with a fresh hotkey.
A martingale can post a top Sortino for months, farm emissions, then blow up. Pure burn lets the farmer re-register cheaply. A large lock with a slow drain keeps capital at risk through the detection window so the blow-up strands the bond.
Owner settings
p = 90%, k = 0.2
anti-tail-risk preset
Break-even before ban
E* ≈ 0.83 · T
must farm this much just to recover costs
Honest miner
τ1 sunk
τ9 lock releases as real edge earns incentive
The owner sets p = 90% and k = 0.2:
btcli sudo set --netuid 42 --name collateral_lock_share --value 0.9 # 90% (raw 58982 also accepted)
btcli sudo set --netuid 42 --name collateral_drain_ratio --value 0.2Registration now charges the same floating price, split τ1 burned + τ9
locked. The farmer's arithmetic inverts: farming E before validators stop
scoring the hotkey yields E (emissions) + 0.2·E (released collateral)
− T (price paid) — they must farm E* = T / 1.2 ≈ 0.83·T before detection
just to break even, and each detected cycle strands the rest of a fresh
τ9 lock. The honest miner's costs are nearly unchanged: τ1 sunk (the burn),
and a τ9 lock they release by doing exactly what they registered to do.
Validator enforcement. The chain side needs nothing from validators — the lock and drain run themselves. The validator's whole job is the two invariants from enforcement: score by hotkey with persistent history, and stop scoring hotkeys whose returns show the martingale signature. Stranding follows automatically:
import bittensor as bt
blacklist: set[str] = load_state("blacklist") # persists across restarts
history: dict[str, list[float]] = load_state("returns") # keyed by HOTKEY, not uid
async with bt.Subtensor() as client:
metagraph = await client.subnets.metagraph(42)
for neuron in metagraph.neurons:
returns = history.setdefault(neuron.hotkey, [])
returns.extend(await fetch_new_returns(neuron)) # gaps never improve a score
# A top-percentile Sortino with no downside observations IS the signature.
if is_martingale(returns) or neuron.hotkey in blacklist:
blacklist.add(neuron.hotkey)
scores[neuron.uid] = 0.0 # zero incentive: drain freezes, bond strands
else:
scores[neuron.uid] = sortino(returns)
await client.execute(bt.SetWeights(netuid=42, weights=normalize(scores)), wallet)A GPU marketplace with per-machine deposits (Lium)
The Lium pattern: miners bring machines, each machine must be backed by a deposit, pulling a rented machine forfeits it, and an honest departure winds down cleanly. The chain provides amount-agnostic rails; the per-machine policy lives in validator code.
Miners back each machine with alpha collateral. add_collateral funds the bond; set_min_collateral parks a floor so the drain cannot undercut the deposit. An honest wind-down clears the floor and keeps earning; pulling a rented machine zeroes the score and strands what is left.
Owner settings
p = 50%, k = 1
modest reg bond + fast deposit drain
Published policy
25α / machine
validators read collateral_locked on the metagraph
4 machines
100α floor
add then set-min; incentive refills shortfalls
Owner config — a modest registration bond plus deposit-friendly drain:
btcli sudo set --netuid 51 --name collateral_lock_share --value 0.5 # p = 50%
btcli sudo set --netuid 51 --name collateral_drain_ratio --value 1.0 # k = 1The subnet publishes its policy in validator code: 25α of collateral per
machine. Sizing the deposit in incentive-terms matters: if one machine
earns ~1α/tempo, a 25α deposit at k = 1 takes ~25 tempos of scored work to
drain — so an exiting miner's wind-down lasts about one rental term, which is
exactly the notice period the business wants.
Miner flow — bring 4 machines, lock ~τ100 of collateral (free stake on the hotkey is used first; only the shortfall is bought), then set a 100α floor so the lock holds:
btcli collateral add --netuid 51 --amount-tao 100 -w my_coldkey -H my_hotkey
btcli collateral set-min --netuid 51 --min-alpha 100 -w my_coldkey -H my_hotkeyadd takes a TAO-value; the floor is in alpha. The floor stops the drain
at 100α, and if the lock ever dips under (say the miner raises the floor
for a fifth machine before funding it), incentive fills the gap
automatically. No re-locking, no bot.
Validator enforcement — collateral rides the metagraph, so the check
costs zero extra calls: every neuron row carries collateral_locked,
collateral_min (the miner's floor), and collateral_earned (lifetime
incentive since the bond existed):
import bittensor as bt
PER_MACHINE_ALPHA = 25
async with bt.Subtensor() as client:
metagraph = await client.subnets.metagraph(51)
for neuron in metagraph.neurons:
machines = await verify_hardware(neuron) # the subnet's own attestation
required = machines * PER_MACHINE_ALPHA
if neuron.collateral_locked is None or neuron.collateral_locked.alpha < required:
scores[neuron.uid] = 0.0 # under-collateralized: no rentals, no incentive
continue
route_rentals(neuron, machines)
scores[neuron.uid] = availability_score(neuron)For hotkeys not in the metagraph — deregistered miners whose bonds persist
(dormant bonds, the population most likely to return) — use
subnet_collateral: every collateral entry
on the subnet with uid (None when deregistered), owning coldkey, and the
derived terms headroom_alpha (portion actively draining above the floor),
shortfall_alpha (capture in progress below it), and
releasable_work_alpha (incentive still needed to release the headroom).
Exit protocol — the deposit leaves through the same door it drains through:
- The miner signals departure (the subnet's API, or an on-chain
set_commitmentraw call) and clears the floor:btcli collateral set-min --netuid 51 --min-alpha 0. - Validators stop routing new rentals to them but keep scoring the machines still serving existing rentals — and waive the coverage floor for a miner in wind-down.
- With the floor cleared and incentive still flowing, the ordinary drain
returns the deposit at
k × incentiveper tempo; by the time the last rental ends, most of the 100α is withdrawable again. - Pulling a rented machine instead zeroes their score immediately: drain stops, the remaining deposit strands, and it stays stranded unless validators resume scoring them (forgiveness) or they return and mine it out. Their track record — keyed by hotkey — is waiting for them either way.
The deterrence is the same stranding mechanism as everywhere else in this system; what the marketplace adds is only sizing (per machine) and the wind-down convention, both of which live in the subnet's own code.
A miner's lifecycle on a collateral subnet
Price τ10, p = 80%, k = 1:
- Register: pay τ10 — τ2 burned, τ8 staked to your hotkey and locked
(about 8 alpha at an alpha price of τ1). A
CollateralLockedevent records it; query your entry underMinerCollateral(netuid, hotkey). - Mine: you earn 0.5 alpha of incentive per tempo. Each tempo releases 0.5 alpha of the lock. After ~16 tempos of that rate you are fully released; everything you earn is withdrawable immediately either way.
- Get pruned at 3 alpha still locked: the 3 alpha freezes. Nothing to do, nothing lost.
- Re-register next week: requirement is 80% of the current price, your 3 alpha lock is credited at the subnet's moving-average price, and you top up only the shortfall — plus the burned share, which is always charged.
- Quit forever: the remaining lock stays frozen on the hotkey. It is still yours, still earning pool appreciation, but only mining releases it.
Budgeting notes for miners
- Total capital at the door is the full price
Tregardless ofp; the difference is how much of it you can earn back. Check both the price and the split before registering:
btcli query burn --netuid 42 --json
btcli sudo get --netuid 42 --name collateral_lock_share
btcli sudo get --netuid 42 --name collateral_drain_ratio- The lock is denominated in alpha units at lock time. Its TAO value floats with the pool — collateral on a subnet you believe in is not dead weight, and collateral on a subnet you attack devalues with your attack.
- Unstake math: your withdrawable balance on the subnet is your total alpha
minus conviction locks minus collateral locks.
remove_stake,recycle,burn_alpha, and stake moves all respect the guard (they fail withStakeUnavailableif they would dip into locked collateral). - Registration fails with
NotEnoughBalanceToStakeif your coldkey cannot cover the burned share plus your collateral top-up.
Owner guidance
p decides how much of the entry price is accountability rather than toll;
k decides how long it takes a good miner to work it off:
p = 0— pure burn, exactly the pre-collateral chain behavior. The safe default; nothing changes for your subnet until you opt in.- Moderate bond (
p = 75%,k = 1) — general-purpose deterrence: sybils and squatters forfeit; honest miners recover at par. - Anti-tail-risk (
p = 83–90%,k = 0.2–0.5) — subnets whose scoring can be gamed on short horizons (trading, forecasting): a large lock with a slow drain keeps your fastest apparent earners collateralized through your detection window. - Fast release (
p = 67%,k = 2) — capital gate at entry with a minimal ongoing lockup, for low-stakes work.
Both settings apply prospectively only — every miner's lock and drain
ratio are snapshot at their registration — so raising p never retro-locks
incumbents, and neither parameter can be used to rug standing collateral.
The lock share is capped at 95%
(MaxCollateralLockShare):
the burned share must stay positive so re-registration always costs a
nonzero, floating burn. The drain ratio must be positive (a k of zero
would make the lock unrecoverable — a burn with extra steps) and at most 10.
Chain reference
Terms — the shared vocabulary for validators and dashboards, as returned
by subnet_collateral (and, for registered
neurons, as per-uid vectors on the metagraph):
- locked — the bond: what a blacklist strands and re-registration credits.
- min_locked — the floor: the miner's standing commitment.
- earned — lifetime incentive since the collateral relationship began;
compare against the detection budget
E* = max(T ÷ (1 + k), (1 − p)·T)to see how far a miner is from having "paid off" their bond. Lives and dies with the entry. - headroom =
locked − min_locked— the portion actively draining; zero with a floor set means parked at commitment. - shortfall =
min_locked − locked— capture in progress: incentive is filling a raised floor instead of being paid out. - releasable work =
headroom ÷ k— incentive still needed to release everything above the floor. - dormant bond —
locked > 0with nouid: a deregistered miner whose capital waits on the subnet; the population most likely to return.
Storage —
CollateralLockShare,
CollateralDrainRatio,
MinerCollateral holding
MinerCollateralState { locked, drain_ratio, min_locked, earned }.
Extrinsics —
add_collateral
and
set_min_collateral
(miner, must own the hotkey);
sudo_set_collateral_lock_share,
sudo_set_collateral_drain_ratio
(owner-or-root, rate-limited, admin-window gated).
Events — CollateralLocked { netuid, hotkey, locked, total_locked } on
registration and add_collateral; MinCollateralSet { netuid, hotkey, min_locked }; CollateralLockShareSet / CollateralDrainRatioSet on
hyperparameter changes.
Errors —
CollateralLockShareTooHigh
(owner tried to set p above 95%),
CollateralDrainRatioOutOfBounds
(owner tried to set k ≤ 0 or above 10). Miners hit the pre-existing
NotEnoughBalanceToStake (can't cover burn + top-up) and StakeUnavailable
(unstake would dip into locked collateral).
Related
Registration burn,
add_collateral,
set_min_collateral,
miner-collateral,
subnet-collateral,
collateral_lock_share,
collateral_drain_ratio,
emissions