Skip to content

workspace: add the Anchor programs CI never linted - #126

Merged
mikemaccana merged 2 commits into
claude/anchor-v2-migration-d5hkh4from
claude/workspace-lint-coverage
Aug 20, 2026
Merged

workspace: add the Anchor programs CI never linted#126
mikemaccana merged 2 commits into
claude/anchor-v2-migration-d5hkh4from
claude/workspace-lint-coverage

Conversation

@mikemaccana

Copy link
Copy Markdown
Collaborator

Stacked on #123. Retarget to main once that merges, and do not merge this into a dead branch. The two commits here need the v2 port because the dependency conflict below only exists under anchor-spl 2.0.0-rc.1.

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. 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, as people touched them; the Anchor ones never were. No commit message, comment or issue justifies the omission.

Three structural fixes were needed

  • 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. This means 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() (which returns a reference already), .clone() on CpiHandle/CpiHandleMut (both Copy), mut on bindings that are already &mut, #[instruction(...)] parameters only a seeds expression reads, and three crates missing the unexpected_cfgs check-cfg declaration the rest of the repository carries.

Two needed more than the mechanical fix. 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, which made the one field no handler reads look unused; they are pub now, like every other accounts struct here.

One lint fix was a real bug, caught by the tests. 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 a caller cannot get wrong.

Verification

101 workspace members resolve. cargo fmt --check and cargo clippy -- -D warnings -A clippy::diverging_sub_expression both clean across all of them.


Generated by Claude Code

claude added 2 commits August 19, 2026 23:28
`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)
`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)
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