Subnets choose their emission split · Runtime v480 · October 2026
Before Etao every subnet paid the same fixed split. With Etao the owner moves the dial — here an SN4-style subnet pays miners 62% instead of 41% — and root TAO stakers' slice of the pie does not move. Illustrative numbers.
Etao hands every subnet owner the dial that has been welded shut since launch: how the subnet's alpha emission is divided. Until now every subnet paid the same split — 18% to the owner, 41% to validators, 41% to miners. From spec 480 a subnet that lives on its miners can pay them 62%. A subnet that needs deep validation can push validators to the 50% cap. An owner who wants to signal commitment can set their own cut to zero.
One extrinsic, one rate limit, five rules, and a guarantee underneath all of it: root TAO stakers are paid exactly what they would be on an untouched subnet, whatever the owner picks. The guarantee is not a promise; it is arithmetic the chain runs at every change.
Etao ships to mainnet as a sudo runtime upgrade from main. Payouts in the first post-upgrade block are identical to the last pre-upgrade block; nothing moves until an owner moves it. The complete, standalone release note — every rule, error, storage item and worked CLI example — is the Etao release guide.
Subnets are not alike. Some are miner-heavy compute markets where validation is cheap and the scarce resource is miner effort. Some are judgment-heavy and need validators to spend real money to score work. Some are owner-run products where the owner cut funds the team; others want that cut gone so every token flows to participants. A single fixed split cannot serve all of them, and until now the only knob — the owner cut — was a global sudo setting, the same for every subnet.
The obstacle to letting owners move the validator share was root. Root TAO stakers are paid from the validator slot of every subnet. Cut that slot from 41% to 20% and, with nothing else changing, root's income from the subnet would halve: owners could tax a network-wide stakeholder to pay their own participants. Etao removes that coupling. The validator slot becomes a choice about validators, and root's payout is pinned to a baseline the owner cannot move.
Every subnet now carries a five-slot vector [burn, recycle, owner, validator, miner]. Each slot is a u64 share of u64::MAX, so the five slots sum to exactly one with no rounding dust. Per block, alpha_out × owner accrues to the owner, alpha_out × validator to the validator bucket and alpha_out × miner to the miner bucket.
| Slot | Paid to | Rule in v1 |
|---|---|---|
burn | nothing — alpha is destroyed | must be 0 (reserved) |
recycle | nothing — alpha returns to the unissued pool | must be 0 (reserved) |
owner | the subnet owner's hotkey | 0% to 33%; lease-created subnets at least 18% |
validator | validator dividends (root TAO stakers are paid from this slot) | at most 50%, and high enough that root's baseline share is reachable |
miner | miner incentive | at least 33% |
The setter is AdminUtils.sudo_set_subnet_emission_weights(netuid, uids, values). It is sparse: name the slots you want to change and their new shares; the others keep their value. The merged vector must pass every rule, and each rule has its own error so a rejection names the constraint. Callers are the subnet owner coldkey or root. Owners may change a subnet's vector once every 50,400 blocks (about seven days). The limit is keyed by subnet, not by coldkey, so handing a subnet to a new owner does not reset it; a subnet's first change is free, and root is exempt.
Root TAO is weighted against alpha by a TAO weight w. Each block, the alpha root stakers receive from a subnet is
root_alpha = V × x / (x + A) × alpha_out with x = root_tao × w
where V is the validator slot and A the subnet's alpha issuance. Before Etao, w was the single global TaoWeight and V was fixed everywhere.
Etao gives every subnet its own effective TAO weight w_s (SubnetTaoWeight), used on the consensus side of that subnet only: the root share carved out of the validator slot, the TAO-versus-alpha split of validator dividends, and the stake weighting inside Yuma Consensus. Every accepted set call solves w_s once, at that block, from live chain values and the new validator slot alone:
# 1. root's baseline share of this subnet's emission
r = V0 × x_g / (x_g + A) x_g = root_tao × TaoWeight (global)
V0 = validator share of the default vector (0.41)
# 2. the weight that pays r under the new validator slot
x_new = r × A / (V_new − r)
w_s = x_new / root_tao
# rejected with ValidatorEmissionTooLowToPreserveRoot if V_new ≤ r or w_s > 1
# equivalently, the validator floor at this block is
V_min = r × (1 + A / root_tao)So the block after any change, root TAO stakers earn from the subnet exactly what an untouched subnet would pay them at that block. Lowering V raises w_s; raising V lowers it; the alpha root receives does not move. Two properties follow from anchoring to a fresh baseline rather than to root's current share:
w_s. An owner who raises V while the subnet is young and lowers it after issuance grows — or the reverse — ends up with the same w_s and the same root share as an owner who made the final change in one step. Root's payout is a function of the chain's state, not of the owner's history.V to exactly V0 clears the per-subnet entry, so the subnet follows the global TaoWeight again. A subnet that has never changed its validator share has no entry at all.Between sets w_s is frozen — never recomputed per block. The weight is capped at one (root TAO never counts more than 1:1 against alpha), so not every V is reachable: on a mainnet subnet with 5.44M TAO on root, 6.46M alpha issued and TaoWeight = 0.18, root's baseline is about 5.4% of emission and the validator slot can go down to about 11.8%. The floor moves with root stake, issuance and the global weight, so btcli subnets emission show prints the live value and every write checks it locally before anything is signed.
What does not change. The pool side never sees w_s. tao_in, alpha_in, the alpha-injection cap and RootProp use the global TaoWeight, exactly as before. Changing a subnet's vector changes how its alpha is distributed; it does not change how much TAO or alpha is injected into its pool, prices, swaps, or the emission the subnet receives.
The upgrade runs one migration, seed_subnet_emission_weights_v1, which seeds every live subnet from its legacy owner-cut state so that the first post-upgrade block pays out exactly what the last pre-upgrade block did:
owner is the legacy SubnetOwnerCut when OwnerCutEnabled was true, else 0; validator is half the remainder; miner is what is left, absorbing the rounding ulp.SubnetTaoWeight entry is written, so every subnet keeps following the global TaoWeight until its owner changes the vector.SubnetCreatedViaLease is set for subnets with a live lease mapping, and SubnetOwnerCutAccrued is seeded to the exact deduction the legacy lock refund applied — including subnets already mid-dissolution — so no refund changes.New subnets are seeded with the default vector [0, 0, 18%, 41%, 41%]. Dissolving a subnet clears its vector, weight, lease marker, accrued owner cut and rate-limit key, so a reused netuid starts clean.
Deprecated extrinsics. sudo_set_subnet_owner_cut and sudo_set_owner_cut_enabled keep their call indices and signatures but always return Deprecated. Set the owner slot — including to zero — through sudo_set_subnet_emission_weights instead. SubnetOwnerCut and OwnerCutEnabled remain readable as legacy views but are no longer written.
SubnetEmissionWeights (the vector), SubnetTaoWeight (Option<u64>; absent = follows global), SubnetCreatedViaLease, SubnetOwnerCutAccrued.SubtensorModule.SubnetEmissionWeightsSet { netuid, weights } with the full post-merge vector.OwnerHyperparamUpdate(Hyperparameter::EmissionWeights) keyed by subnet in LastRateLimitedBlock; constant SubnetEmissionWeightsRateLimit = 50_400.SubnetInfoRuntimeApi.get_subnet_emission_weights(netuid) (API version 3); get_subnet_hyperparams_v3 adds owner_emission, validator_emission and miner_emission.setSubnetEmissionWeights(netuid, uids, values) and getSubnetEmissionWeights(netuid) returning the vector and the lease flag.subnet_emission_weights read (vector, shares, effective and global TAO weight, root's current and baseline share, the live validator floor, rate-limit state), the SetSubnetEmissionWeights intent with a structured before/after preview, and the pure rules module bittensor.emission_weights.btcli subnets emission with show, set, set-value, increase and decrease; --json and --dry-run everywhere; fixed exit codes (0 done, 1 missing subnet or blocked, 2 rule violation).Look before you touch. The Allowed table is live for this block:
btcli subnets emission show --netuid 4
Vector
owner 18.00%
validator 41.00%
miner 41.00%
Root
root share of emission 5.4015%
root baseline share 5.4015%
effective tao weight 18.00% follows the global TaoWeight (18.00%)
next owner change now first change; owners may change once per 50,400 blocks
Allowed
owner 0.00% to 33.00%
validator 11.8093% to 50.0000% the floor is where root's baseline share needs a TAO weight of 100%
miner >= 33.00%Preview with --dry-run; the plan shows the before/after vector, root's share before and after, and the TAO weight move:
btcli subnets emission set --netuid 4 --owner 18% --validator 20% --miner 62% --dry-run
dry run: set emission weights on netuid 4: owner=18.00% validator=20.00% miner=62.00%
effect vector: owner 18.00% / validator 41.00% / miner 41.00% -> owner 18.00% / validator 20.00% / miner 62.00%
effect root earns 5.4015% of this subnet's emission now and 5.4015% after (its baseline:
default validator share, global TaoWeight); the subnet's TAO weight moves 18.00% -> 43.89%Then drop --dry-run, or nudge one slot at a time:
btcli subnets emission increase --netuid 4 --slot miner --by 5% btcli subnets emission decrease --netuid 4 --slot owner --by 0.02 btcli subnets emission set-value --netuid 4 --slot owner --value 0 # owner cut off
A rejected vector exits 2 before anything is signed and names the rule and the allowed range:
error: the chain would reject this change: ValidatorEmissionTooLowToPreserveRoot: validator (slot 3)
is 5.0000%; ... right now the validator share must be at least about 11.8093%
note: allowed on subnet 4 right now: validator 11.8093% to 50.0000%
help: btcli subnets emission show --netuid 4 prints the vector and every allowed rangeSubnetEmissionWeightsSet events.TaoWeight remains the governance lever over root's weight.btcli write validates locally and shows the exact floor, so test with --dry-run first.SubnetOwnerCut / OwnerCutEnabled as legacy views; expect SubnetEmissionWeightsSet events and Deprecated from the two retired extrinsics.Runtime spec_version 480, transaction_version unchanged. Delivered to mainnet as a sudo runtime upgrade from main. Migration seed_subnet_emission_weights_v1, idempotent. Reference pages: Etao release guide (the complete standalone note), Emission weights (the concept page), set-subnet-emission-weights, subnet-emission-weights, validator_emission, and the source in emission_weights.rs.