A two-line refactor can drop the check that guards a vault.

Some of Solana's largest losses came down to one account nobody checked: Wormhole (~$320M), Cashio (~$48M), Crema (~$8.8M). In Anchor, a check that was written is one line in a struct, and a later pull request can delete it without touching any logic. It compiles and the tests still pass. This page catches that case: a check that was there, and a change that removes it.

escrow · withdrawrefactor: simplify Withdraw accounts
    #[account(
        mut,
        seeds = [b"vault", depositor.key().as_ref()],
        bump,-       has_one = depositor,    )]-   pub vault: Account<'info, Vault>,+   pub vault: UncheckedAccount<'info>,

2 account checks removed

  • Anchor no longer checks that vault is a Vault this program owns.
  • vault no longer has to belong to the signing depositor.

Whether that is exploitable depends on what else pins the account (here the seeds still do). That is the question a reviewer has to answer, and solinv puts it in front of them.

Check yours

Paste a pull request, or the address of a deployed program to see what each upgrade changed. It runs in your browser; nothing to install.

What this page does, and what needs solinv installed

This page reads what a program declares. Installed, solinv also runs the program and tries the attack each check exists to stop.

On this pageWith solinv installed
One public pull request at a time, when you paste itEvery pull request, private repositories too: the build fails when a check is removed, with a note on the line
Code already pushed to GitHub, or deployedYour local branch, before you push
Reads the declarations and key checks at the top of the handler. A check inside a function the handler calls looks removed hereRuns the program locally and tries what each check prevents: skipping a signer, passing a fake owner or type, forging a PDA, swapping in another user's account. You learn whether the check is really enforced, wherever it lives
Deployed Anchor programs with an on-chain IDLAny Anchor program from its source, plus a map of the instructions that rely on hand-written checks
A shared quota of lookupsNo limit

Fail the pull request that removes a check

Add this to a workflow. No Solana toolchain and no build of your program.

steps:
  - uses: actions/checkout@v7
  - uses: psyto/solinv@v0

Or run it locally

cargo install --git https://github.com/psyto/solinv --tag v0.1.9 solinv-cli
solinv diff --base-src old/src --head-src programs/my_program/src
solinv idl target/idl/my_program.json --src programs/my_program/src

To fuzz the checks, start from your IDL: solinv writes most of the spec from it.