Skip to content

BZetsu/MultiSig-Vault

Repository files navigation

Multisig Vault (Anchor 0.32)

A Solana program (Anchor 0.32) that holds SOL in a multi-signature vault. Only the program can move funds out; no single key can withdraw on its own.


User flow (plain terms)

1. Someone creates the vault

One person (the creator) sets up the vault and defines the rules:

  • Who can move money: a list of N people (by wallet address), up to 5.
  • How many must agree: a number M (e.g. “2 of 3”).
  • Max per 24 hours: e.g. no more than X SOL per day.
  • Initial 2FA code: a number used for the first withdrawal.

After that, the vault exists and has one treasury account that holds SOL. Only the program can move SOL out, and only when the rules are met.

2. Anyone can put money in

Any wallet can send SOL to the vault (deposit). No approval and no check of “who is allowed.” If you know the vault’s address, you can send SOL to it. The vault holds that SOL until a withdrawal is executed under the rules.

3. Withdrawing: propose → approve → execute

  • Propose – One of the authorized signers creates a withdrawal proposal: “Send X SOL to address Y.”
  • Approve – Other authorized signers approve that proposal. When at least M of the N signers have approved (e.g. 2 of 3), the proposal is ready.
  • Execute – Anyone can call execute (a signer or a bot). The program only sends SOL if:
    • The proposal has enough approvals (M-of-N),
    • The correct 2FA (TOTP) code is sent with the execute call,
    • The amount is within the 24-hour spend limit,
    • The proposal has not already been executed. After a successful withdrawal, the 2FA code rotates for the next time.

So in short: create the vault (set who can withdraw and the limits) → anyone can deposit → only the fixed list of signers can propose and approve; money actually leaves only when enough have approved, the right 2FA is given, and the 24h limit is not exceeded.


PDAs

  • VaultState[b"vault", creator]

    • creator, signers (max 5), threshold
    • totp_code
    • spend_limit, spent_in_window, window_start
    • release_nonce, proposal_count
    • bump, authority_bump
  • ProposalState[b"proposal", vault, proposal_id]

    • vault, proposer, destination, amount
    • approvals
    • executed
    • proposal_id, bump
  • ProgramAuthority[b"authority", vault]

    • System-owned account (no data) that holds the SOL.

Instructions (short)

  • initialize_vault(signers, threshold, spend_limit, initial_totp)
    Set up the vault: signers, threshold, spend limit, initial TOTP, and authority PDA.

  • deposit(amount)
    Anyone can send SOL into the vault’s authority PDA. Checks amount > 0.

  • create_proposal(destination, amount)
    Only a signer can call. Creates a ProposalState, auto‑adds proposer to approvals. Checks signer, amount > 0, and amount <= spend_limit.

  • approve_proposal()
    Only a signer can call. Adds caller to proposal.approvals. Fails if already approved or proposal executed.

  • execute_withdrawal(totp_code)
    Checks, in order:

    1. Proposal not executed
    2. approvals.len() >= threshold
    3. totp_code == vault.totp_code
    4. 24h window reset and spend tracking
    5. spent_in_window + amount <= spend_limit

    If all pass, transfers lamports from authority PDA to destination, sets executed = true, updates spent_in_window and release_nonce, and rotates TOTP:
    totp_code = release_nonce * 7 + 111111.


Errors

  • NotAuthorizedSigner
  • AlreadyApproved
  • InsufficientApprovals
  • Invalid2FACode
  • SpendLimitExceeded
  • ProposalAlreadyExecuted
  • InvalidThreshold
  • InvalidAmount

Tests

All tests are in tests/multisig-vault.ts and run with:

cd multisig-vault
anchor test

They cover:

  • Deposit 3 SOL into the vault.
  • Create a proposal and collect 2 approvals.
  • Execute withdrawal with the correct TOTP.
  • Check TOTP rotation (release_nonce == 1, totp_code == 111118).
  • Execute withdrawal with a wrong TOTP and see it fail.

Test screenshot

All tests passing


Devnet

  • Program ID: 6p7fCjYTpz1V9HeyRzN2Z9CpDK6zaUPGwDHHQK1KQ4hL

Deployed with:

cd multisig-vault
anchor build
anchor deploy --provider.cluster devnet

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors