solana-anchorlisted
Install: claude install-skill iktok90-design/ai-smart-contract-auditor
# Solana / Anchor (Rust) detection
## When this applies
- Any `.rs` file importing `anchor_lang` (`use anchor_lang::prelude::*`)
- Macros `#[program]`, `#[derive(Accounts)]`, `#[account]`, `#[instruction(...)]`
- Account wrappers `Signer<'info>`, `Account<'info, T>`, `AccountInfo<'info>`, `UncheckedAccount`, `Program<'info, T>`, `Sysvar<'info, T>`
- PDA derivation: `seeds = [...]`, `bump`, `find_program_address`, `create_program_address`
- CPI: `CpiContext`, `invoke`, `invoke_signed`, `*_cpi`
Solana has no implicit caller. Every authority, ownership, and identity invariant must be asserted explicitly in the account struct or handler.
## Detection patterns
### Missing signer check (CRITICAL)
```rust
#[derive(Accounts)]
pub struct Withdraw<'info> {
pub authority: AccountInfo<'info>, // ← not Signer; nobody proves they're authority
#[account(mut)]
pub vault: Account<'info, Vault>,
}
```
**Signal:** an "authority"/"owner"/"admin" account typed `AccountInfo`/`UncheckedAccount` instead of `Signer<'info>`, or a handler reading `ctx.accounts.x` without checking `x.is_signer`. Anyone passes the real authority's pubkey without their signature.
### Missing owner check / arbitrary account substitution (CRITICAL)
```rust
let data = ctx.accounts.state.to_account_info();
let state = State::try_from_slice(&data.data.borrow())?; // ← no owner check
```
**Signal:** deserializing from a raw `AccountInfo`/`UncheckedAccount` without verifying `account.owner == program_id`, or