Subnets choose their emission split · Runtime v480 → v481 · 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: it is paid off the top of the validator slot every block, at the chain's live baseline. 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 every block.
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 | root's baseline share first, then alpha validator dividends | at most 50%, and strictly above root's live baseline share |
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 the global TAO weight w (TaoWeight, 0.18 on mainnet today). Before Etao, the alpha root stakers received from a subnet each block was
root_alpha = V × x / (x + A) × alpha_out with x = root_tao × w
where V was the fixed 41% validator slot and A the subnet's alpha issuance. Etao keeps exactly that payout and detaches it from the owner's choice of V. Every block, for every subnet, the chain computes root's baseline share and pays it off the top of the validator slot:
# root's baseline share of this subnet's emission, recomputed every block
r = V0 × x / (x + A) x = root_tao × TaoWeight (global)
V0 = validator share of the default vector (0.41)
# what root is paid, and what alpha validators share
root_alpha = min(V, r) × alpha_out
validator_alpha = (V − min(V, r)) × alpha_out
# a set is rejected with ValidatorEmissionTooLowToPreserveRoot if V_new ≤ r
# (validators would get nothing); the floor at this block is r itselfr is what root would earn from the subnet right now if the owner had never touched the vector. Because it is recomputed from live state on every block, root's payout tracks the baseline continuously — as issuance grows against root TAO, as root stake moves, or as governance changes TaoWeight — with no further call from anyone. A subnet whose owner never changes the vector pays exactly what the chain paid before Etao.
V from 41% to 20% takes the whole 21 points from alpha validators; root's slice is the same before and after. Raising V likewise pays only alpha validators more. There is no per-subnet weight to solve, store or ratchet.TaoWeight. Stake weighting inside Yuma Consensus, the TAO-versus-alpha split of validator dividends, child/parent stake and the pool side all use the global knob exactly as before Etao.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, so the validator slot can go down to anything strictly above 5.4%. 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.
The capped case. The check runs at set time while the baseline keeps moving. If r later grows past a subnet's V, root's cut is capped at the whole validator slot and alpha validators receive nothing until the owner raises V; root is never paid more than the slot. show flags the capped state and the runtime API reports both the baseline and the share actually paid.
What does not change. The pool side is untouched. 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 v480 upgrade ran 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.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.The v481 upgrade runs remove_subnet_tao_weight_v1, which deletes the SubnetTaoWeight entries the v480 set-time solve had written — the per-block baseline replaces them — and touches nothing else. Subnets whose legacy owner cut was disabled were seeded with a 50% validator slot and paid root 0.50 × x / (x + A) under v480; from v481 they pay the global baseline 0.41 × x / (x + A) like every other subnet, about 18% less root alpha on those subnets and correspondingly more to their alpha validators.
New subnets are seeded with the default vector [0, 0, 18%, 41%, 41%]. Dissolving a subnet clears its vector, 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), 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) returning the vector, root_baseline_share and the root_share actually paid; 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, the global TAO weight, root's baseline share and the share paid, what alpha validators keep, the capped flag, 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% paid off the top of the validator slot
root baseline share 5.4015% default validator share, global TaoWeight (18.00%); recomputed every block
validators after root 35.5987% what alpha validators share once root is paid
validator floor > 5.4015% a change must leave the validator share above the baseline
next owner change now first change; owners may change once per 50,400 blocks
Allowed
owner 0.00% to 33.00%
validator 5.4015% to 50.0000% must exceed root's baseline share, which is paid off the top of this slot
miner >= 33.00%Preview with --dry-run; the plan shows the before/after vector, root's share before and after, and what alpha validators keep:
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 keeps its baseline 5.4015% of this subnet's emission (default validator share,
global TaoWeight) before and after; alpha validators get 35.5987% -> 14.5985%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%; root is paid its baseline share of emission off the top of this slot every block,
so right now the validator share must be above 5.4015% or validators would get nothing
note: allowed on subnet 4 right now: validator 5.4015% to 50.0000%
help: btcli subnets emission show --netuid 4 prints the vector and every allowed rangeshow reports this as capped). Watch SubnetEmissionWeightsSet events.TaoWeight — and paid before alpha validators see anything. Owners cannot move it in either direction and it needs no call from anyone to stay current; the only cap is the validator slot itself. The global 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 481 (the vector shipped in 480), transaction_version unchanged. Delivered to mainnet as a sudo runtime upgrade from main. Migrations seed_subnet_emission_weights_v1 (480) and remove_subnet_tao_weight_v1 (481), both 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.