Skip to content

approve staged Squads transactions from test-cli - #208

Open
kaze-cow wants to merge 1 commit into
kaze/sc-439-add-ability-to-submit-transaction-to-a-squads-multisig-tofrom
kaze/squads-approve-staged-transaction
Open

kaze-cow wants to merge 1 commit into
kaze/sc-439-add-ability-to-submit-transaction-to-a-squads-multisig-tofrom
kaze/squads-approve-staged-transaction

Conversation

@kaze-cow

Copy link
Copy Markdown
Contributor

Description

Adds --squads-transaction-index, which approves an already-staged Squads vault transaction instead of proposing a new one. Before voting, the CLI rebuilds the instructions for the command and checks that the staged transaction holds exactly those.

Motivation

#177 lets one member stage a transaction, but every other member then has to approve it in the Squads UI, and the UI only shows the raw instructions. With this flag, a second member runs the same test-cli command with the transaction index, and their vote only goes through if the staged transaction matches what the command would have sent. See SC-439.

This was split out of #177 so that PR only covers staging and this one can be reviewed on its own. It's based on #177's branch.

Considerations

What gets checked before approving

Multisig::approve in test-cli/src/utils/squads/mod.rs refuses to vote unless all of the following hold:

  • the signer is a member with the vote permission
  • the transaction is for the vault given by --squads-vault-index
  • its stored message equals the message compiled from the command's instructions, and it has no ephemeral signers
  • it isn't stale (the multisig's members or threshold haven't changed since it was staged)
  • its proposal is active and the signer hasn't already voted. If nobody opened a proposal, one is opened first. Draft, approved, rejected, executed and cancelled proposals are rejected with a specific error.

This is the critical part to review: the message comparison is the only thing tying a vote to the intended instructions.

Generated client

Comparing messages needs the Proposal and VaultTransaction accounts, so they're added back to test-cli/squads-idl/generate.mjs, along with their generated types. The message encoder goes back to going through the generated VaultTransactionMessage, so both proposing and approving build the same struct that gets compared.

Tests

Unit tests cover approving a matching transaction, opening a missing proposal, and each of the rejection cases above.

How to test

just lint
cargo test -p cow-test-cli

To try it end to end: stage a transaction with one member as in #177, then run the same command again as a second member with --squads-transaction-index <index>. Changing any argument should fail with "holds different instructions than this command builds".

🤖 Generated with Claude Code

Adds --squads-transaction-index, which approves the existing vault
transaction at that index instead of proposing a new one, after checking
it holds exactly the instructions the command builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kaze-cow
kaze-cow requested a review from a team as a code owner October 19, 2026 07:09
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.

1 participant