Skip to content

Hotfixes: Locked transfer flags to control locked alpha transfers + ema-price based emissions#2780

Closed
gztensor wants to merge 2 commits into
mainfrom
hotfix/tx-flags-ema-price-emissions
Closed

Hotfixes: Locked transfer flags to control locked alpha transfers + ema-price based emissions#2780
gztensor wants to merge 2 commits into
mainfrom
hotfix/tx-flags-ema-price-emissions

Conversation

@gztensor

Copy link
Copy Markdown
Contributor

Description

  1. Switch subnet emissions to price-based shares and root-proportion injection cap
  • get_shares now uses the subnet price EMA (SubnetMovingPrice) so emission is proportional to normalized price over emit-enabled subnets.
  • Alpha injection cap is now root_proportion * alpha_emission, so older subnets (lower root proportion) transition from liquidity injection to chain buys.
  • Update/repair affected emission tests; drop obsolete TAO-flow share tests.
  1. Add a new map AccountFlags to subtensor pallet that stores a u128 bitmap of account flags. The bit0 flag controls whether the account can receive locked alpha. The new extrinsic set_reject_locked_alpha allow the coldkey to set it's own reject locked alpha flag.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Other (please describe):

Checklist

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have run ./scripts/fix_rust.sh to ensure my code is formatted and linted correctly
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

@gztensor gztensor self-assigned this Jun 22, 2026
@github-actions github-actions Bot added the hotfix This PR needs to be merged very quickly and will likely skip testing on devnet and testnet label Jun 22, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🚨🚨🚨 HOTFIX DETECTED 🚨🚨🚨

It looks like you are trying to merge a hotfix PR into main. If this isn't what you wanted to do, and you just wanted to make a regular PR, please close this PR, base your changes off the devnet-ready branch and open a new PR into devnet ready.

If you are trying to merge a hotfix PR, please complete the following essential steps:

  1. go ahead and get this PR into main merged, so we can get the change in as quickly as possible!
  2. merge main into testnet, bumping spec_version
  3. deploy testnet
  4. merge testnet into devnet, bumping spec_version
  5. deploy devnet
  6. merge devnet into devnet-ready

If you do not complete these steps, your hotfix may be inadvertently removed in the future when branches are promoted to main, so it is essential that you do so.

@gztensor gztensor added skip-cargo-audit This PR fails cargo audit but needs to be merged anyway and removed hotfix This PR needs to be merged very quickly and will likely skip testing on devnet and testnet labels Jun 22, 2026
@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

🛡️ AI Review — Skeptic (security review)

VERDICT: SAFE

LOW contributor risk: established subtensor contributor with write permission, substantial recent PR history, no Gittensor allowlist hit found; branch is explicitly a hotfix to main.

Static Skeptic review found no .github/ai-review, Copilot-instruction, dependency, lockfile, or build-script changes. The PR body explicitly justifies the direct main target as a hotfix. I did not run builds or tests per Skeptic rules.

Findings

No findings.

Conclusion

No malicious intent or security vulnerability was identified in the diff. The runtime changes use checked/saturating arithmetic paths, signed self-service flag updates, and locked-alpha receipt checks without introducing an origin bypass or panic path.


🔍 AI Review — Auditor (domain review)

VERDICT: 👍

Gittensor association UNKNOWN by allowlists; author has write permission and substantial recent subtensor PR history, so contributor-risk calibration is low.

PR body is substantive and matches the implementation: price-EMA subnet emissions, root-proportion alpha injection cap, and a self-service locked-alpha receipt flag.

Duplicate-work check: PR #2746 overlaps on account receiving flags, but it is a broader feature branch with unrelated runtime/tooling scope. This PR is the better candidate for the focused main hotfix subset; recommend treating #2746 separately.

Spec version is bumped in the diff (419 -> 421). No auto-fixes were applied and tests were not run; static review was sufficient for the remaining low-risk helper-ordering issue.

Findings

Sev File Finding
LOW pallets/subtensor/src/staking/lock.rs:1371 Validate locked-alpha receipt before copying decaying flags inline

Prior-comment reconciliation

  • 0c677842: not addressed — The code still inserts destination DecayingLock rows before ensure_can_receive_locked_alpha_with_flag can fail.

Conclusion

No blocking domain issue was found. One low-risk helper ordering issue remains from the prior review, but the PR is still appropriate to approve as a focused hotfix.


📜 Previous run (superseded)
Sev File Finding Status
LOW pallets/subtensor/src/staking/lock.rs:1370 Validate locked-alpha receipt before copying decaying flags ➡️ Carried forward to current findings
The code still inserts destination DecayingLock rows before ensure_can_receive_locked_alpha_with_flag can fail.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review — see the sticky summary comment for the verdict and the inline comments below for specific findings.

Comment on lines +1369 to +1370
for (netuid, decaying) in decaying_locks_to_transfer.iter() {
DecayingLock::<T>::insert(new_coldkey, *netuid, *decaying);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[LOW] Validate locked-alpha receipt before copying decaying flags

swap_coldkey_locks copies DecayingLock entries to new_coldkey before the new AccountRejectsLockedAlpha check runs. If old_coldkey has a decaying/perpetual flag and a non-zero rolled lock, a direct helper failure can leave the destination DecayingLock mutated even though the function returns an error. The public extrinsic path appears to rely on storage-layer rollback, but the helper's own no-mutation-on-error invariant and test do not cover these flags, and a stale flag can affect the mode of later locks for that coldkey/netuid. Build rolled_locks_to_transfer and run all rejection checks first, then insert the DecayingLock entries in the commit phase with the lock moves.

@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: SAFE Auditor: 👍

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review — see the sticky summary comment for the verdict and the inline comments below for specific findings.

Comment on lines +1369 to +1371
for (netuid, decaying) in decaying_locks_to_transfer.iter() {
DecayingLock::<T>::insert(new_coldkey, *netuid, *decaying);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[LOW] Validate locked-alpha receipt before copying decaying flags

swap_coldkey_locks still copies DecayingLock rows to new_coldkey before the locked-alpha rejection check runs. If this helper is called outside the public extrinsic's transactional storage layer, an AccountRejectsLockedAlpha error can leave destination decaying flags behind even though no locks moved. Build and validate rolled_locks_to_transfer first, then copy the decaying flags in the mutation phase after validation succeeds; add a helper-level failure assertion that DecayingLock is absent on the destination.

@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: SAFE Auditor: 👍

@gztensor

Copy link
Copy Markdown
Contributor Author

Replaced by #2781

@gztensor gztensor closed this Jun 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-cargo-audit This PR fails cargo audit but needs to be merged anyway

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant