Repository navigation
feat(cli): vote subcommands for vault-controlled vote accounts (MUL-2311, 1/3) - #207
Closed
bguillaumat-squads wants to merge 2 commits into
Closed
bguillaumat-squads wants to merge 2 commits into
bguillaumat-squads wants to merge 2 commits into
Conversation
…ount Validators that make a Squads vault the authorized withdrawer of their vote account had no way to operate it from open source tooling: the CLI only offered raw-byte vault transactions. Add `vote withdraw`, `update-commission`, `authorize`, `update-identity` and `update-commission-collector` (SIMD-0232), one operation per proposal like the solana CLI. Each command checks that the vault is the withdrawer, simulates the vault instructions before proposing, and asks for an extra confirmation when the withdrawer or a commission collector would leave the multisig's vaults. display-transaction now labels vault accounts and decodes vote instructions, since approvers on a hardware wallet only see the outer Squads instruction. Part of MUL-2311.
Part of MUL-2311.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
|
should this work actually be ported over to the newer |
bguillaumat-squads
deleted the
feature/mul-2311-v4-cli-first-class-validator-commands-vote-account-stake
branch
November 6, 2026 23:27
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of MUL-2311 (1 of 3: vote account. Next: stake account commands, then the version bump and release).
What
New
vote <op>subcommands let a validator manage a vote account whose authorized withdrawer is a Squads vault, using only the open source CLI:vote withdraw(--amount <SOL>|--all|--close)vote update-commissionvote authorize(--authority-type voter|withdrawer)vote update-identity(the new identity co-signs at execution:vault-transaction-execute --extra-keypair)vote update-commission-collector(--kind inflation-rewards|block-revenue, SIMD-0232)Each command creates one vault transaction and its proposal (one operation per proposal, like the
solana vote-*commands).display-transactionnow labels vault accounts(vault N)and decodes vote instructions, because approvers on a hardware wallet only see the outer Squads instruction. The README documents the commands and adds a validator runbook.Why
A validator asked whether they can operate a Squads-controlled vote account without any third-party UI. Before this PR, the CLI only offered
vault-transaction-createwith a raw serialized message, which nobody can use by hand (see also MUL-740).How
vault_proposal.rs): flattened common flags (--vault-indexis required, no auto-detection), then onepropose()that builds the same VaultTransactionCreate + ProposalCreate (+ ProposalApprove) transaction as the existinginitiate-*commands. Existing commands are untouched.--vault-index; otherwise the command stops with an error.sig_verify: false, and the result is shown above the message hash. A failed simulation asks "propose anyway?" (default no) rather than refusing, because some operations fail now but succeed later (a commission change outside the allowed part of the epoch).display-transaction. Voter changes are not flagged, since voters are normally hot keys.--amountwithdrawal that would leave the account below its rent-exempt minimum is refused, since it can never execute.solana-vote-interface2.x (the version in the lockfile) cannot deserializeVoteStateV4, which is live on mainnet (SIMD-0185).UpdateCommissionCollectoris not insolana-vote-interface2.x, so it is hand-encoded as[17,0,0,0,kind,0,0,0]. The bytes and account metas matchupdate_commission_collectorinsolana-vote-interface6, and it executed on chain in the end-to-end run below. Version 6 can't be used here: it needs a newersolana-pubkeymajor and Rust 1.89.Authorize(Voter)with "invalid instruction data".vote authorize --authority-type voternow stops before proposing on such accounts and points tosolana vote-authorize-voter-checked, signed by the current voter. That command was checked to work on a BLS account: it builds the BLS variant itself. Supporting the BLS voter change from the multisig is left as a follow-up.solana-vote-interface = { version = "2.2", features = ["bincode"] }. It is already inCargo.lockat 2.2.6 throughsolana-program, so no new crate is downloaded.initiate-transfer(split into its own change), the stake commands (next PR), and the crate version bump (with the release PR).Acceptance criteria (vote part)
update_commission_collector_matches_simd_0232, plus ix 17 executed on chain. The other four ops use the officialsolana-vote-interfacebuilders.--extra-keypairsolana-test-validator4.3, with the mainnet Squads program and program config cloned (details under Testing).check_vote_account_requires_the_vault_as_withdrawer; end to end with--vault-index 1→ "Vault … (index 1) is not the authorized withdrawer …"display-transactionflags_withdrawer_moving_out_of_the_multisig; end to end, declining the warning proposed nothing; a collector moved outside the vaults showed the red flag indisplay-transaction.display-transactiondecodes every instruction these commands produceinstruction_decodetests, and checked on every proposal in the end-to-end run.create_signer_from_path.Testing
End to end on
solana-test-validator4.3.0-rc with--clone-upgradeable-program SQDS4ep65…and the program config cloned from mainnet. Setup: a threshold-1 multisig, and a vote account created by solana CLI 4.3 (V4 layout with a BLS key) with vault 0 as withdrawer. Commands were driven through a pty, because of the dialoguer prompts.update-commission10% → 5%, on chain.withdraw --amount 1.25: the recipient gained 1.25 SOL.update-identity, executed with--extra-keypair: the identity changed, and a block revenue collector pointing at the vault stayed on the vault.update-commission-collector:authorize withdrawer→ vault 1: no warning; the withdrawer changed.withdraw --all, then--close, from vault 1: the account was closed.--approve→display-proposals→proposal-vote --action Approve→ execute.Refusals and errors:
Not run: Ledger; a voter change on a vote account without a BLS key (a 4.3 validator always creates one); mainnet.
Independent review: two rounds. Fixed:
--amount.Dismissed, with evidence:
--allignores pending delegator rewards": SIMD-0123 is inactive on mainnet, and the simulation would catch it.Pre-PR advisor check:
display-transaction; the dust guard was added;solana vote-authorize-voter-checkedadvice fails on BLS accounts", which was run and works.Risk / rollout
CLI only: no program, migration or backend change. The existing commands are unchanged apart from
display-transaction, which prints extra labels and decoded rows. Publishing waits for the release PR, so nothing ships until then.Follow-ups:
display-transactiondecoding for vote instructions newer than 2.x, and for*WithSeedauthority moves.get_multisigin the SDK reports an RPC failure as "AccountNotFound: … error sending request".