Skip to content

Root claim#2053

Merged
sam0x17 merged 58 commits intodevnet-readyfrom
root-claim2
Oct 29, 2025
Merged

Root claim#2053
sam0x17 merged 58 commits intodevnet-readyfrom
root-claim2

Conversation

@shamil-gadelshin
Copy link
Collaborator

@shamil-gadelshin shamil-gadelshin commented Sep 12, 2025

Root Claim

This PR introduces a root claim mechanism. It replaces the automatic selling of root-alpha dividends with accumulation. Users can either:

  • Manually claim their accumulated share, or
  • Enable auto-sell, which automatically sells the accumulated share daily and transfers the proceeds to their account.

New extrinsics

  • set_root_claim_type — Set root-claim mode: auto or manual.
  • claim_root — Manually claim accumulated root dividends.

Storage changes

  • PendingRootAlphaDivs — Tracks root-alpha dividends between epochs.
  • RootClaimType — User’s preferred claim mode (auto or manual).
  • RootClaimable — User’s claimable share of alpha dividends.
  • RootClaimed — Accounting helper for alpha dividends (stake changes, claimed amounts).
  • StakingColdkeysByIndex — Supports randomized distribution of auto-claims per block.
  • StakingColdkeys — Supports root-dividends distribution.
  • NumStakingColdkeys — Count to support randomized auto-claim distribution per block.
  • NumRootClaim — Number of auto-claims to fulfill for a subnet in the current epoch.
  • AlphaMapLastKey — Supports staking coldkey migration.

Removed (obsolete storage maps)

  • TaoDividendsPerSubnet
  • PendingAlphaSwapped

Original PRs


PendingEmission::<T>::remove(netuid);
PendingRootDivs::<T>::remove(netuid);
PendingAlphaSwapped::<T>::remove(netuid);
PendingRootAlphaDivs::<T>::remove(netuid);
Copy link
Contributor

Choose a reason for hiding this comment

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

PendingRootAlphaDivs::<T>::remove(netuid) is called twice: line 318 & 351

Copy link
Contributor

@antlerminator antlerminator left a comment

Choose a reason for hiding this comment

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

Pardon for the intrusion but I've heard this PR was close/ready to be merged yet after reading it I found a bunch of things that could be addressed 😬

log::debug!("hotkey: {hotkey:?} tao_take: {tao_take:?}");
let validator_stake = Self::increase_stake_for_hotkey_and_coldkey_on_subnet(
log::debug!("hotkey: {hotkey:?} alpha_take: {alpha_take:?}");
let _validator_stake = Self::increase_stake_for_hotkey_and_coldkey_on_subnet(
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
let _validator_stake = Self::increase_stake_for_hotkey_and_coldkey_on_subnet(
Self::increase_stake_for_hotkey_and_coldkey_on_subnet(

Is there a reason we keep the variable here?

pub fn add_stake_adjust_root_claimed_for_hotkey_and_coldkey(
hotkey: &T::AccountId,
coldkey: &T::AccountId,
amount: u64,
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this be AlphaCurrency, similarly to how it's done in remove_stake_adjust_root_claimed_for_hotkey_and_coldkey?

Comment on lines +1896 to +1904
#[pallet::storage] // --- MAP ( hot ) --> MAP(netuid ) --> claimable_dividends | Root claimable dividends.
pub type RootClaimable<T: Config> = StorageMap<
_,
Blake2_128Concat,
T::AccountId,
BTreeMap<NetUid, I96F32>,
ValueQuery,
DefaultRootClaimable<T>,
>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this be renamed to RootClaimableRatio to reflect it better what this exactly is? This wording is already used elsewhere in the code

@shamil-gadelshin
Copy link
Collaborator Author

Pardon for the intrusion but I've heard this PR was close/ready to be merged yet after reading it I found a bunch of things that could be addressed 😬

Thanks for the review. I addressed the majority of your comments.

sam0x17
sam0x17 previously approved these changes Oct 27, 2025
@antlerminator
Copy link
Contributor

Per discussion on the Open Dev call and the overall initiative of improvement of bookkeeping in Bittensor, can we please implement proper bookkeeping from the start for root claim? Back when I was reviewing this PR I saw two possibilities:

  • Emit event/events with the exact amounts of alpha that's being received or tao that was received due to selling
  • Add new storage variable that tracks the amount of alpha/tao that was just received, e.g., LastRootClaimed where for non-root netuids it'd track alpha received and for root netuid it'd track amount of tao received by selling other alphas (this name is not 100% ideal though)

Relevant discussion from CoR: https://discord.com/channels/1120750674595024897/1245487232928714863/1431026852008427572

Copy link

@dougsillars dougsillars left a comment

Choose a reason for hiding this comment

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

it looks like root claim now charges fees to convert to tao?

netuid,
owed_u64.into(),
T::SwapInterface::min_price::<TaoCurrency>(),
false,

Choose a reason for hiding this comment

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

so we are charging a swap fee on root stakeholders now?

Choose a reason for hiding this comment

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

Adding fees has not been part of the public description of how this would function, afaik. Previous open discussions were that the default would function as it is now (just the option to continue to receive in TAO). The recent Discord announcement does say "If you do nothing, your claims use Swap", but this could be construed as the two options of root_claim_type and not the traditional swap with fees.
Is the intention for all root stakers to pay fees to receive dividends?

@bdmason
Copy link
Contributor

bdmason commented Oct 29, 2025

Hey @shamil-gadelshin it looks like (apologies if I've misunderstood) the following is correct:

  1. user unstakes from root
  2. RootClaimed is reduced by what wasn't claimed but was claimable
  3. user can restake and claim what they forgot to claim before step 1

If this is correct, there is likely to be an awful lot of dust that's effectively burned, but not actually burned as it's still technically accessible, though a user may have to earn more divs first to get over the threshold required to make a claim.

Would it not be better to just claim any outstanding divs when the user unstakes? Whilst there would be more operations on the unstake call, there won't be a never ending accumulation of storage in RootClaimed for all the dust left behind.

@sam0x17 sam0x17 merged commit f190dca into devnet-ready Oct 29, 2025
53 of 57 checks passed
@shamil-gadelshin
Copy link
Collaborator Author

Per discussion on the Open Dev call and the overall initiative of improvement of bookkeeping in Bittensor, can we please implement proper bookkeeping from the start for root claim? Back when I was reviewing this PR I saw two possibilities:

  • Emit event/events with the exact amounts of alpha that's being received or tao that was received due to selling
  • Add new storage variable that tracks the amount of alpha/tao that was just received, e.g., LastRootClaimed where for non-root netuids it'd track alpha received and for root netuid it'd track amount of tao received by selling other alphas (this name is not 100% ideal though)

Relevant discussion from CoR: https://discord.com/channels/1120750674595024897/1245487232928714863/1431026852008427572

We plan to update this feature after the release.

@leemcmullen
Copy link

@shamil-gadelshin The PR description is confusing, it says:

set_root_claim_type — Set root-claim mode: auto or manual.

and

RootClaimType — User’s preferred claim mode (auto or manual).

Neither of which are true.

In fact, RootClaimType is either Swap or Keep. There is an enum with auto and manual options, but that's called RootClaimFrequencyEnum and doesn't seem to be used anywhere else in the subtensor codebase?

@antlerminator
Copy link
Contributor

@shamil-gadelshin doing this after the release will mean that the off-chain bookkeeping is impossible between the release and that update... Basically the historical state will be "corrupted" so why not do it now? This is not a huge change in itself but it's impossible to do by non-core devs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking-change This PR introduces a noteworthy breaking change 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.