Skip to content

Add transferStakeFrom and approve functions to staking precompile#2478

Merged
sam0x17 merged 9 commits intoopentensor:devnet-readyfrom
jeremyp-tao:jeremy-staking-precompile-approvals
Apr 7, 2026
Merged

Add transferStakeFrom and approve functions to staking precompile#2478
sam0x17 merged 9 commits intoopentensor:devnet-readyfrom
jeremyp-tao:jeremy-staking-precompile-approvals

Conversation

@jeremyp-tao
Copy link
Copy Markdown

Description

Adds new functions to the staking precompile similar to ERC20 transferFrom and approve, which will allow smart contracts to atomically receive alpha tokens and react to the transfer, which is not possible today (if an user transfers alpha token to a smart contract, the latter is not aware of this transfer). Allowance is managed per netuid for finer control.

Related Issue(s)

None

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

None

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)

Not applicable

Additional Notes

None

@open-junius open-junius self-requested a review March 3, 2026 00:39
}

#[precompile::public("increaseAllowance(bytes32,uint256,uint256)")]
fn increase_allowance(
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.

We can use approve interface to do increase/decrease allowance, and they are not in the standard ERC20 definition.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Contracts can easily get the current allowance and increase it atomically (they must check for re-entrancy attacks), however users cannot do that. That's why those functions are very common in tokens implementing ERC20.

@open-junius
Copy link
Copy Markdown
Contributor

It is better to implement both function in an Alpha wrapper contract, instead of in precompile. @ppolewicz @camfairchild any update for ERC20-alpha-wrapper

Comment on lines +63 to +66
<R as frame_system::Config>::AccountId,
// For each pair of (spender, netuid)
Blake2_128Concat,
(<R as frame_system::Config>::AccountId, u16),
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.

What happens on subnet de-reg?

Copy link
Copy Markdown
Author

@jeremyp-tao jeremyp-tao Mar 25, 2026

Choose a reason for hiding this comment

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

I'm not sure a de-reg would cause any issue. There approve would still be here but the user can update the allowance at anytime, and is suppose to trust/verify that the contract will do appropriate things with the approved funds. So I think it is not worth it to complicate the design.

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.

After de-reg, we need clean up the data, the transfer alpha doesn't work for de-reg netuid.
And for approved allowance, there are two options.

  1. just clean up the storage
  2. transfer alpha according to each allowance with the same netuid.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Clearing the storing with the netuid prefix is a bad idea because there can be a lot of entries, and it is not safe in general to have unbounded storage storage writes.

If a netuid is de-reg, calling transferStakeFrom will revert like transferStake even if there is allowance, because under the hood they call the same dispatchable. Once the netuid is registered again however, the transfers will work again (if user have funds in the new alpha), and allowance will be preserved.

For the last point (allowance preservation), I think this is not the issue as stated in my previous comment. If the user trust (or verify code) the contract with a long-live high amount allowance to not be malicious and transfer the funds in unwanted way, there is no reason the contract will behave differently after the de-reg/re-reg. If one think a contract may go rogue in the future, they should either not interact with it or make a short-live exact amount approval and consume it quickly.

In any case at the protocol level I don't see any risk of keeping the allowances across netuid de-regs, as they don't interact directly with the staking pallet, and instead ends up being a normal transferStake call (on the behalf of the approver) only when the spender call transferStakeFrom.

Do you see a concrete issue I missed?

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.

If a subnet is de-registered, its netuid will be locked and no one can use it again before all data are cleaned up. But it could be reused again after all old data removed from the storage. So the new registered subnet is different one even the netuid is the same, means the alpha is not the same.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Clearing big storage maps is risky in Substrate in general :/

For the approvals as said above it's not really a problem imo that they stay across netuid de-reg/re-reg. Users trust the smart contract to not consume the approval without a valid reason.

Approvals are just numbers which allows transfering stake on the behalf of the approver. After de-reg/re-reg, the approver will have no stake and the transferFrom will fail because the transfer part itself will fail in the pallet (like if you called yourself transfer). If they stake for this new network with same netuid, their previous approval will still be there and transfer could be made indeed, but they already trusted the contract so it should not be an issue. If they don't trust the contract long-term, they should like with ERC20 only approve the required amount to be consumed in a short timeframe, returning the allowance back to 0.

So I really so no issue of keeping the allowance data in storage.

@open-junius
Copy link
Copy Markdown
Contributor

please merge devnet-ready, will fix the failed CI tasks.

@sam0x17 sam0x17 merged commit 1ce8574 into opentensor:devnet-ready Apr 7, 2026
191 of 195 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants