> ## Documentation Index
> Fetch the complete documentation index at: https://docs.inkwell.finance/llms.txt
> Use this file to discover all available pages before exploring further.

# Multisig integration

> Dagon Payroll checks one thing about the admin: that the company's authority signed. Squads v4, Altitude, Clearsig and Realms all qualify. Authority rotation is two-step.

> **CONFIDENTIAL & PROPRIETARY © 2026 Inkwell Finance, Inc. All Rights Reserved.**
>
> This document is for informational purposes only and does not constitute legal, tax, or investment advice, nor an offer to sell or a solicitation to buy any security or other financial instrument. Any examples, structures, or flows described here are design intent only and may change.

The program checks exactly one thing about the admin:

```rust theme={null}
authority.is_signer && authority == company.authority
```

Every multisig that executes instructions by `invoke_signed` from a PDA
satisfies that. So does a plain keypair or an MPC key.

## The authority instruction set

Twelve instructions are authority-only. They are the only ones a multisig
ever has to approve:

`update_policy`, `set_operator`, `propose_authority`, `accept_authority`
(signed by the new authority), `add_employee`, `update_salary`,
`approve_bonus`, `set_employee_active`, `open_pay_run`, `close_pay_run`,
`approve_treasury_withdrawal`, and `retarget_withdrawal` (treasury
withdrawals).

They share five properties, and each property exists because some
multisig needs it:

| Property | Why it matters |
| - | - |
| Fixed-width arguments only (`Pubkey`, `u64`, `u8` / `bool`) | Clearsig intent templates can only encode fixed-width parameters. |
| At most 6 accounts per instruction | Clearsig allows 16 accounts per instruction. Squads and Realms transactions have a 1232-byte cap. |
| No fresh keypair co-signers | Clearsig and Realms have no ephemeral signers. Squads has them, but its UI can't add real keypairs. |
| No Encrypt CPI | Encrypt charges fees from a per-payer deposit PDA (`["encrypt_deposit", payer]`). Keeping authority instructions off Encrypt means the vault never needs an Encrypt deposit. |
| The vault can be the rent payer | `add_employee` and `open_pay_run` take a separate `payer` that may equal the vault. |

### Why no fresh signer and no Encrypt CPI

Every ciphertext the program creates is a fresh account that must sign its
own creation, and every Encrypt CPI charges its fee to the payer's Encrypt
deposit. A multisig vault cannot supply either cleanly.

So the work is split:

* **The multisig approves policy.** It passes handles, wallets, periods,
  budgets and caps. No ciphertext is created and Encrypt is never called.
* **Cranks and employees do the Encrypt work.** `sync_treasury`,
  `init_employee_ledger`, `prepare_pay_run` and the withdrawal steps create
  ciphertexts from fresh keypairs. `process_payment` and `process_bonus` run
  the pay graph. Whoever submits the instruction pays the Encrypt fee from
  their own deposit. Crank steps are permissionless (payments can be
  restricted to a designated operator) and bounded by the policy the
  multisig approved: run budget, per-payment cap, optional operator.

Salary and bonus ciphertexts are created by HR off-chain with Encrypt
`CreateInput`, before the proposal exists. The proposal only references
them.

> [!NOTE]
>
> `grant_view` is not in the authority set. It creates a ciphertext (the
> viewer's copy), so it needs a fresh keypair and an Encrypt CPI. The
> authority is permitted to call it, but it does not share the properties
> above.

## Squads v4

* Program `SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf`, the same on mainnet
  and devnet. The vault PDA is `["multisig", multisig, "vault", index]`.
* Create the company with `authority` set to the vault PDA. Fund it by
  sending the payroll mint from the vault to the company's vault token
  account, in the same proposal as `open_pay_run` if you like.
* **Tested against the mainnet binary.** The integration test loads the
  Squads v4 program dumped from mainnet. A 2-of-2 multisig proposes,
  approves and executes **one** vault transaction containing
  `update_policy + add_employee + open_pay_run`, with the vault as authority
  *and* rent payer. Permissionless cranks then pay the employee. The test
  also checks that a lone member signing directly is rejected.
* SDK: `SquadsV4Authority` provides `proposeIxs` → `approveIx` →
  `executeIx`. See [SDK quickstart](https://docs.inkwell.finance/dagon/payroll/sdk-quickstart.md).

## Altitude

Altitude is Squads' business-account product. Its treasury is a
Squads-controlled smart account, and its vault address is the `authority`.

* If the account is on **Squads v4**, use `SquadsV4Authority` unchanged.
* **Unverified:** some newer Squads accounts live on the Smart Account
  program (`SMRTzfY6DfH5ik3TKiyLFfXexV8uSG3d2UksSCYdunG`). The payroll
  program is unaffected, but proposals must be built with that program's
  SDK. Check the owner program of the Altitude account on-chain before
  wiring it up.

## Clearsig

Clearsig is its own multisig program (devnet
`53aZBmukjX5sYxbrYVRDd2DWzsRWVmvVFPY6PcyomR5v`, pre-alpha). Signers approve
a **human-readable message** that the program renders from an intent
template and re-verifies. It then executes the templated instructions with
its vault PDA (`["vault", wallet]`) signing. Third-party programs integrate
by registering **custom intents** (JSON) on the wallet.

The SDK's `clearsigIntents()` generates 12 templates, one per authority
instruction. For example:

```text theme={null}
open_pay_run:  "Payroll {company}: run payroll for period 202609, total budget ceiling 250000"
add_employee:  "Payroll {company}: hire {wallet} with encrypted salary {ct}"
```

PDAs (employee record, run record, withdrawal record) are passed as
`address` parameters. The payroll program re-derives and checks them, so a
wrong address fails.

> [!WARNING]
>
> **Open question.** Clearsig's schema doc lists "arbitrary program
> interaction" as review-only in some versions, while `execute_custom`
> exists in its code. Confirm with the Clearsig maintainers that custom
> intents execute before relying on Clearsig for payroll. Clearsig is
> pre-alpha and devnet-only.

Clearsig's own notes on Encrypt pre-alpha testing say its frontend calls
Encrypt `createInput`, so HR-side salary encryption fits its UX.

## SPL Governance / Realms

The native treasury PDA `["native-treasury", governance]` signs via
`invoke_signed` in `execute_transaction`, so it works as `authority`. Use
`serializeInstructions()` from the SDK to paste the authority instructions
into Realms as custom instructions.

## Fireblocks / MPC custody

MPC custody produces an ordinary Ed25519 signature, so it works directly as
`authority` or as a Squads member.

## Rotating the authority

Moving a company between multisigs (for example Squads to Clearsig) takes
two steps:

1. From the current multisig: `propose_authority(new_authority)`.
2. From the new multisig: `accept_authority`, signed by the new authority.

The Company PDA does not change. It is seeded by the authority it was
created for, stored as `seed_authority`, so every existing record, vault
and employee address stays valid. The rotation test runs a full pay and
withdraw cycle **after** the rotation to prove vault payouts still sign.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.