Skip to content

Added root_claim_for#2784

Open
evgeny-s wants to merge 4 commits into
devnet-readyfrom
feat/root_claim_for
Open

Added root_claim_for#2784
evgeny-s wants to merge 4 commits into
devnet-readyfrom
feat/root_claim_for

Conversation

@evgeny-s

@evgeny-s evgeny-s commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Description

This PR adds a new claim_root_for function to be able to call root claim on behalf of another coldkey.

Related Issue(s)

  • Closes #[issue number]

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):

Breaking Change

If this PR introduces a breaking change, please provide a detailed description of the impact and the migration path for existing applications.

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

Screenshots (if applicable)

Please include any relevant screenshots or GIFs that demonstrate the changes made.

Additional Notes

Please provide any additional information or context that may be helpful for reviewers.

@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 thread pallets/subtensor/src/macros/dispatches.rs
Comment thread precompiles/src/staking.rs Outdated
@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

🛡️ AI Review — Skeptic (security review)

VERDICT: SAFE

BASELINE scrutiny: evgeny-s has repo write permission, an account from 2012, substantial contribution history, and no matched Gittensor allowlist signal; branch feat/root_claim_for -> devnet-ready.

No .github/ai-review/* or .github/copilot-instructions.md changes are present. The current diff removes the previously-added claim_root_for surface and exposes only a self claimRoot(uint16[]) precompile that dispatches the existing signed claim_root call for the EVM caller-derived account.

Findings

No findings.

Prior-comment reconciliation

  • 9c3ffd83: addressedclaim_root_for is no longer present in the current diff, so no new runtime call index is added or reused.
  • 148e9940: addressed — The arbitrary-target claim_root_for path was removed. The remaining maybe_add_coldkey_index call is reached through the existing self claim_root signed path using the caller-derived account, not an arbitrary supplied coldkey.

Conclusion

SAFE because the prior arbitrary-target root-claim path and duplicate runtime call-index issue are no longer present, and I found no malicious code or new security vulnerability in the remaining self-claim precompile wrapper.


📜 Previous run (superseded)
Sev File Finding Status
HIGH pallets/subtensor/src/macros/dispatches.rs:2184 claim_root_for reuses an existing runtime call index ✅ Addressed
claim_root_for is no longer present in the current diff, so no new runtime call index is added or reused.
HIGH pallets/subtensor/src/staking/claim_root.rs:358 Arbitrary coldkeys can pollute the root auto-claim index ✅ Addressed
The arbitrary-target claim_root_for path was removed. The remaining maybe_add_coldkey_index call is reached through the existing self claim_root signed path using the caller-derived account, not an arbitrary supplied coldkey.

🔍 AI Review — Auditor (domain review)

VERDICT: 👍

Gittensor: UNKNOWN direct allowlist match; author has repo write permission and substantial prior PR history, so reviewed as an established contributor.

The Auditor proposed a replacement PR description, but the current body is non-trivial; not overwriting. Maintainers: ask the Auditor to regenerate if you want it.

Implementation adds StakingPrecompileV2.claimRoot(uint16[]) as a self-claim wrapper over the existing SubtensorModule::claim_root, with shared pallet-side subnet validation via do_root_claim_checked and EVM/ABI coverage.

Description discrepancy: the current one-sentence PR body says this claims on behalf of another coldkey, but the implementation and Solidity docs only support self-claim for the EVM caller's derived coldkey. I populated proposed_pr_body with a corrected description because the existing body is otherwise template/trivial.

Spec-version auto-fix was not applied: this sandbox could not resolve dev.chain.opentensor.ai, so I could not safely compare local spec_version: 423 to live devnet.

Findings

No findings.

Conclusion

No blocking domain issues found in the diff. The remaining risk is the normal devnet spec-version CI check, which I could not confirm from this network-restricted environment.

@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: VULNERABLE

@evgeny-s evgeny-s added the skip-cargo-audit This PR fails cargo audit but needs to be merged anyway label Jun 23, 2026
@evgeny-s evgeny-s changed the title Added root_claim_for + precompiles for root_claim/root_claim_for Added root_claim_for Jun 23, 2026

@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.

Error::<T>::InvalidSubnetNumber
);

Self::maybe_add_coldkey_index(&coldkey);

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.

[HIGH] Arbitrary coldkeys can pollute the root auto-claim index

claim_root_for accepts any signed origin and passes an arbitrary coldkey into this shared helper. The helper indexes that coldkey before do_root_claim proves the coldkey has any root stake; for a coldkey with no staking hotkeys, try_do_root_claim simply iterates an empty vector, deposits RootClaimed, and commits. A caller can therefore pay only transaction fees to persistently grow StakingColdkeys, StakingColdkeysByIndex, and NumStakingColdkeys with arbitrary accounts, diluting run_auto_claim_root_divs selection and creating unbounded state bloat. Gate the index insertion on actual root stake, or make claim_root_for reject targets without root stake before calling maybe_add_coldkey_index.

Suggested change
Self::maybe_add_coldkey_index(&coldkey);
ensure!(
Self::coldkey_has_root_stake(&coldkey),
Error::<T>::NotEnoughStakeToWithdraw
);
Self::maybe_add_coldkey_index(&coldkey);

@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: VULNERABLE

@yeuyeuh

yeuyeuh commented Jun 23, 2026

Copy link
Copy Markdown

Concern: claim_root_for is permissionless and, combined with PR #2759, lets anyone force-sell other users' rewards

Under that model, claim_root_for lets any signed account trigger a claim on behalf of any coldkey, with no authorization check. A malicious actor could call claim_root_for on every coldkey staking on a given validator. Since claiming now forces a swap of the basket alpha into TAO, this would create sell pressure on exactly the subnets that validator chose to weight. A malicious actor can force the timing of this sell pressure.

Suggestion: rather than introducing a standalone permissionless claim_root_for, integrate claim_root into the existing staking proxy mechanism. If a coldkey has set a staking proxy, that's an explicit signal of trust that the proxy may claim its rewards on its behalf. This keeps the "claim on behalf of" capability gated behind consent the coldkey has already granted, instead of making it open to anyone.

@evgeny-s

Copy link
Copy Markdown
Collaborator Author

Concern: claim_root_for is permissionless and, combined with PR #2759, lets anyone force-sell other users' rewards

Under that model, claim_root_for lets any signed account trigger a claim on behalf of any coldkey, with no authorization check. A malicious actor could call claim_root_for on every coldkey staking on a given validator. Since claiming now forces a swap of the basket alpha into TAO, this would create sell pressure on exactly the subnets that validator chose to weight. A malicious actor can force the timing of this sell pressure.

Suggestion: rather than introducing a standalone permissionless claim_root_for, integrate claim_root into the existing staking proxy mechanism. If a coldkey has set a staking proxy, that's an explicit signal of trust that the proxy may claim its rewards on its behalf. This keeps the "claim on behalf of" capability gated behind consent the coldkey has already granted, instead of making it open to anyone.

Thanks for sharing the concern, but the thing is that I need to provide a possibility to claim rewards for the coldkey, which doesn't have a private key, like a derivative key for an ,EVM smart contract let's say. This way, there is no possibility of adding a proxy, because it doesn't have a private key.

@yeuyeuh

@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.

/// # Event:
/// * RootClaimed;
/// - On successfully claiming the root emissions for `coldkey`.
#[pallet::call_index(142)]

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.

[HIGH] claim_root_for reuses an existing runtime call index

142 is already assigned to set_reject_locked_alpha later in this pallet. Runtime calls are SCALE-encoded by call index, so a duplicate index makes dispatch bytes ambiguous across the runtime upgrade and can cause one call to decode as the other or make an existing call inaccessible. Assign claim_root_for an unused index, e.g. 143, and update any metadata/tests accordingly.

Suggested change
#[pallet::call_index(142)]
#[pallet::call_index(143)]

Error::<T>::InvalidSubnetNumber
);

Self::maybe_add_coldkey_index(&coldkey);

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.

[HIGH] Arbitrary coldkeys can pollute the root auto-claim index

claim_root_for lets any signed account choose coldkey, and this helper adds that target to StakingColdkeys before proving the target has any root stake. Because try_do_root_claim succeeds even for a coldkey with no staking hotkeys, an attacker can pay fees to persistently add arbitrary coldkeys to the auto-claim sampling set, inflating NumStakingColdkeys and reducing the probability that legitimate root stakers are selected each block. Gate this index insertion on the target currently holding root stake, or only add coldkeys at the root-stake creation paths.

@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: VULNERABLE

@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: SAFE Auditor: 👍

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.

2 participants