Prohibit Vote Account Self-Withdrawals
- Idea
- Draft
- Review
- Accept
- Implement
- Active
Decision brief
Why this proposal matters
Reject a Vote Program Withdraw instruction when the vote account and recipient resolve to the same address. After activation, every authorized self-withdrawal returns InvalidArgument. Other withdrawals are unchanged.
Proposal at a glance
What changes
- Validate the vote account and authorized withdrawer using the existing rules.
- Compare the addresses of the vote account and recipient.
- If the addresses match, return InvalidArgument.
Stakeholder map
Who is affected
Builders & client teams Medium impact
Because the Vote Program is a native builtin, validator clients must implement the same feature-gated behavior before activation.
Action may be requiredValidators & operators Medium impact
After activation, vote account self-withdrawals fail with InvalidArgument. Non-self withdrawals, instruction encoding, and account lists are unchanged.
Action requirement unknownUsers & stakers Impact unknown
No proposal-specific evidence was found for this group.
Action requirement unknownGovernance & ecosystem Impact unknown
No proposal-specific evidence was found for this group.
Action requirement unknownExact source revision
Full proposal document
f1f6c8b05dc2Summary
Reject a Vote Program Withdraw instruction when the vote account and recipient
resolve to the same address. After activation, every authorized self-withdrawal
returns InvalidArgument. Other withdrawals are unchanged.
Motivation
Currently, a Vote Program Withdraw instruction may use the same account as the
vote account and recipient. A partial self-withdrawal that passes existing checks
subtracts and then restores the requested lamports, making it a no-op.
A full self-withdrawal behaves differently. It deinitializes the vote account, subtracts its full balance, and restores the lamports to the same account. This leaves a funded, Vote Program owned, uninitialized account. Anyone else can then initialize that account with their own validator identity and authorities, taking control of the retained balance. Initiating the self-withdrawal requires the existing authorized withdrawer, making the behavior an operator footgun.
Self-withdrawals have no known use case. Rejecting them removes this risk. The
Stake Program already rejects self-withdrawals with InvalidArgument.
New Terminology
N/A
Detailed Design
Vote Program Withdraw processes an instruction in this order:
- Validate the vote account and authorized withdrawer using the existing rules.
- Compare the addresses of the vote account and recipient.
- If the addresses match, return
InvalidArgument. - If the addresses differ, continue existing withdrawal processing.
The new comparison precedes withdrawal amount and account closure checks. It therefore applies to zero, partial, full-balance, and over-balance withdrawals.
The instruction data and account interface do not change.
Alternatives Considered
- Reject only full self-withdrawals. This prevents vote account deinitialization but preserves partial and zero-lamport no-op transactions without a known use.
- Skip deinitialization for full self-withdrawals. This makes them no-ops and leaves a special case that future changes must continue to handle safely.
- Reject self-withdrawals only in the SDK and CLI. Custom transaction builders can bypass client-side checks, so this does not enforce the invariant.
- Keep the existing behavior. This preserves the footgun.
Impact
After activation, vote account self-withdrawals fail with InvalidArgument.
Non-self withdrawals, instruction encoding, and account lists are unchanged.
Because the Vote Program is a native builtin, validator clients must implement the same feature-gated behavior before activation.
Security Considerations
N/A
Evidence graph
Related proposals and rollout
One or more sources are unavailable.
Upstream review record
Upstream discussion & review
GitHub review is editorial context, not evidence of on-chain support, voting, or outcome.
PR #609 · merged SIMD-0609: Prohibit Vote Account Self-Withdrawals 5 comments and reviews · Sep 15, 2026Hello grod220(https://github.com/grod220)! Welcome to the SIMD process. By opening this PR you are affirming that your SIMD has been thoroughly discussed and vetted in the SIMD discussion section(https://github.com/solana-foundation/solana-improvement-documents/discussions/categories/ideas). The SIMD PR section should only be used to submit a final technical specification for review. If your design / idea still needs discussion, please close this PR and create a new discussion here(https://github.com/solana-foundation/solana-improvement-documents/discussions/categories/ideas). This PR requires the following approvals before it can be merged: - At least one approval from a Anza team member: t
GitHub ↗Thanks, topointon-jump(https://github.com/topointon-jump)! ⚠️ Status: Cannot merge yet - Missing approval from: Anza (t-nelson(https://github.com/t-nelson), steviez(https://github.com/steviez), or bw-solana(https://github.com/bw-solana))
GitHub ↗✅ All approvals received! @grod220, you can now merge this by commenting /merge. ✅ Status: Ready to merge
GitHub ↗/merge
GitHub ↗✅ Merge successful! grod220(https://github.com/grod220)'s PR has been merged.
GitHub ↗Provenance
Evidence & technical details
Rollout or chain data, source revisions, freshness and integrity. 2
Provenance
Evidence & technical details
Rollout or chain data, source revisions, freshness and integrity.SIMD
Deployment Status
Feature Gate not yet created
Exact source revision
Sources & integrity
- Proposal document pinned_commit_blob
f1f6c8b05dc205552d3c290a854a438392701107 - simd-document document · stale · Oct 17, 2026
f1f6c8b05dc205552d3c290a854a438392701107
One or more sources are unavailable.
simd.watch community discussion · SIMD-0609
Powered by Giscus · Sign in with GitHub to comment
Community comments load when this section approaches the viewport.