Skip to content

workspace: add the Anchor programs CI never linted, and fix the v1 file that slipped through - #128

Merged
mikemaccana merged 3 commits into
mainfrom
claude/workspace-lint-coverage-v2
Aug 20, 2026
Merged

workspace: add the Anchor programs CI never linted, and fix the v1 file that slipped through#128
mikemaccana merged 3 commits into
mainfrom
claude/workspace-lint-coverage-v2

Conversation

@mikemaccana

Copy link
Copy Markdown
Collaborator

Replaces #126, whose content never reached main. That PR shows as merged, but its base was claude/anchor-v2-migration-d5hkh4 rather than main, and that branch had already merged, so the merge went into a dead branch. This branch is off main and carries the same work plus one fix.

main does not currently compile. perps: let the pool authority retune the funding rate landed after the v2 port, written against v1: Context<T> rather than &mut Context<T>, Signer<'info>, Box<Account<'info, Pool>>, and has_one = authority. Nothing caught it, because perpetual-futures is not a root workspace member, so cargo clippy and cargo fmt --check never see the crate. Adding the members here is what surfaced it. The port is the usual set, with Box<BorshAccount<Pool>> to match every sibling handler and address = pool.authority replacing has_one.

Main's new lending and perpetual-futures test code was also unformatted, for the same reason.

What the workspace change does

cargo fmt --check and cargo clippy -- -D warnings run from the repository root and only see members of the root workspace. 32 Anchor programs were not members. This takes the workspace from 61 members to 101.

They used to be members. The original workspace in 17afe2e7 (2023) listed the tokens, compression and oracles programs alongside basics. a70c93ba (2024), whose subject is "test: Adding test jobs github actions for anchor and solana native", deleted every member after basics/transfer-sol without mentioning it. The native token entries have been re-added one at a time since; the Anchor ones never were.

Three structural fixes

  • Five transfer-hook examples all named their crate transfer-hook, and one workspace cannot hold two packages with the same name. Each package name now carries its variant. [lib] name stays transfer_hook, so Anchor.toml, the IDL and the .so are untouched.
  • Six Anchor programs use anchor-spl's metadata feature, which requires mpl-token-metadata =5.1.2-alpha.2. A caret range excludes pre-releases, so the five native token programs asking for ^5.1.1 could not share a lockfile with them. The native programs now match the pin, which also required bumping their aliased mpl-solana-program from 2.3 to 3.0. The native token examples now compile against a prerelease Metaplex.
  • external-delegate-token-master enabled the metadata feature without using it, so that came off.

The lints those crates had never been run through

Unused imports, needless borrows of .address(), .clone() on CpiHandle/CpiHandleMut (both Copy), mut on bindings already &mut, #[instruction(...)] parameters only a seeds expression reads, and three crates missing the unexpected_cfgs declaration the rest of the repository carries.

Two needed judgement. DISCRIMINATOR_MAP, EXECUTE_DISCRIMINATOR and TX_HOOK_DISCRIMINATOR read as dead code because their only user is the #[cfg(target_os = "solana")] entrypoint the host build compiles out; they are gated the same way rather than deleted. create_collection's account fields were private, making the one field no handler reads look unused; they are pub now.

One lint fix was a real bug caught by the tests. Collapsing transfer_tokens_from_vault's eight arguments by passing the BorshAccount instead of the fields read event.event_id after release_borrow(), and BorshAccount's Deref panics once released. All five betting-market tests failed inside serialized_account.rs. EventSigner now copies the view, ID and bump out while the borrow is live.

Verification

101 workspace members resolve. cargo fmt --check and cargo clippy -- -D warnings -A clippy::diverging_sub_expression clean across all of them. perpetual-futures 28 tests, lending 26, both passing.


Generated by Claude Code

claude added 3 commits August 20, 2026 01:15
`cargo fmt --check` and `cargo clippy -- -D warnings` both run from the
repository root, which only ever sees members of the root workspace. The
finance programs each sat in their project's own `anchor/Cargo.toml`
workspace and nowhere else, so neither job had ever looked at them. They are
now listed in both places: `anchor build` still uses the project workspace,
and CI sees the crates.

Making that pass took three fixes:

- `token-swap` enabled `anchor-spl`'s `metadata` feature without using it.
  That pulls in `mpl-token-metadata =5.1.2-alpha.2`, which cannot resolve
  alongside the `^5.1.1` the native token examples ask for, because a caret
  range excludes pre-releases. The feature is gone rather than dragging five
  unrelated programs onto an alpha.

- The two `mock-switchboard` crates shared a package name, and a lockfile
  cannot hold two path packages called the same thing. The prop-amm one is
  now `mock_switchboard_prop_amm`; `[lib] name` stays `mock_switchboard`, so
  Anchor.toml, the IDL and the .so are untouched, and the dependant renames
  it back with `package = `.

- The lints the crates had never been run through: needless borrows of
  `.address()` (which returns `&Address` already), unnecessary parentheses,
  unused `mut`, a manual `is_multiple_of`, and `#[instruction(...)]`
  parameters that only the `seeds` expression reads.

One of those lint fixes was a real bug. Collapsing
`transfer_tokens_from_vault`'s eight arguments to six by passing the
`BorshAccount` instead of the fields read `event.event_id` after
`release_borrow()`, and `BorshAccount`'s `Deref` panics once the borrow is
released. All five betting-market tests failed with a panic inside
`serialized_account.rs`. `EventSigner` now copies the view, ID and bump out
while the borrow is live, which satisfies `too_many_arguments` and makes the
ordering something the caller cannot get wrong.

Finance tests: betting-market 8, escrow 5, lending 24, order-book 28,
perpetual-futures 26, prop-amm 22, token-fundraiser 18, token-swap 21,
vault-strategy 22.

(cherry picked from commit 29fb3c5)
(cherry picked from commit b5a554b)
`cargo fmt --check` and `cargo clippy -- -D warnings` run from the repository
root and only see members of the root workspace. 32 Anchor programs were not
members, so CI had never looked at them.

They used to be. The original workspace in 17afe2e (2023) listed the tokens,
compression and oracles programs alongside basics. a70c93b (2024), a commit
whose subject is "Adding test jobs github actions for anchor and solana
native", deleted every member after `basics/transfer-sol` without mentioning
it. The native token entries have been re-added one at a time since, as people
touched them; the Anchor ones never were. No commit message, comment or issue
justifies the omission, so this restores it.

Membership needed three structural fixes:

- Five transfer-hook examples all named their crate `transfer-hook`, and one
  workspace cannot hold two packages with the same name. Each package name now
  carries its variant. `[lib] name` stays `transfer_hook`, so Anchor.toml, the
  IDL and the .so are untouched, and nothing path-depends on these crates.

- Six Anchor programs genuinely use `anchor-spl`'s `metadata` feature, which
  requires `mpl-token-metadata =5.1.2-alpha.2`. A caret range excludes
  pre-releases, so the five native token programs asking for `^5.1.1` could not
  share a lockfile with them. The native programs now match the pin. That also
  required bumping their aliased `mpl-solana-program` from 2.3 to 3.0:
  5.1.1 accepts `solana-program >=1.14, <3.0` while the alpha requires 3.0, and
  the mismatch surfaced as "expected `__Pubkey`, found a different `__Pubkey`"
  where those programs bridge Metaplex's instruction types.

- `external-delegate-token-master` enabled the `metadata` feature without
  using it, so that came off.

The lints those crates had never been run through:

- Unused imports in the transfer-hook lib.rs files, where the real users import
  the same names locally.
- Needless borrows of `.address()`, which returns `&Address` already.
- `.clone()` on `CpiHandle` / `CpiHandleMut`, which are `Copy`.
- `mut` on bindings that are already `&mut`.
- `#[instruction(...)]` parameters that only a `seeds` expression reads.
- Three crates were missing the `unexpected_cfgs` check-cfg declaration the
  rest of the repository carries.

Two findings needed more than the mechanical fix. The `DISCRIMINATOR_MAP`,
`EXECUTE_DISCRIMINATOR` and `TX_HOOK_DISCRIMINATOR` constants read as dead code
because their only user is the `#[cfg(target_os = "solana")]` entrypoint, which
the host build compiles out; they are now gated the same way rather than
deleted. `create_collection`'s account fields were private, which made the one
field no handler reads look unused; they are `pub` now, like every other
accounts struct here.

All 56 Anchor projects build and pass: 258 tests.

(cherry picked from commit ea2910c)
(cherry picked from commit e24c1dd)
`perps: let the pool authority retune the funding rate` landed on main after
the v2 port, written against v1: `Context<T>` rather than `&mut Context<T>`,
`Signer<'info>`, `Box<Account<'info, Pool>>`, and `has_one = authority`.

It does not compile, and nothing caught it, because `perpetual-futures` was not
a root workspace member, so neither `cargo clippy` nor `cargo fmt --check` ever
saw the crate. Adding the members in this branch is what surfaced it.

The port is the usual set: `&mut Context<T>`, the `'info` lifetime dropped,
`Box<BorshAccount<Pool>>` to match every sibling handler, and `has_one`
replaced by `address = pool.authority` on the signer.

Also formats main's new lending and perpetual-futures test code, unformatted
for the same reason.

perpetual-futures 28 tests, lending 26.
@mikemaccana
mikemaccana merged commit e0fcaa2 into main Aug 20, 2026
27 of 36 checks passed
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.

2 participants