agents/skills/solana/token-flow-tracing/SKILL.md
Trigger Pattern SPL token CPI transfers, token_account.amount, invoke/invoke_signed, Transfer/TransferChecked - Inject Into Lifecycle, External-Env agents
npx skillsauth add plamentsv/plamen token-flow-tracingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Trigger Pattern: SPL token CPI transfers,
token_account.amount,invoke/invoke_signed,Transfer/TransferCheckedInject Into: Lifecycle, External-Env agents
For every token the protocol handles:
Where can tokens enter?
deposit() / stake() instructions - standard entry points via CPI to Token ProgramFor each entry point:
vault.total_value, pool.total_deposited)token_account.amount read directly for calculations? -> Donation attack vectortoken_account.amount compared anywhere?Red flags:
token_account.amount directlyWhere can tokens leave?
withdraw() / unstake() instructionsFor each exit: does the tracked balance decrease BEFORE or AFTER the CPI transfer? For each transfer call: can the source account be underfunded at execution time? (funds deployed externally, locked, or lent out → transfer reverts)
For each transfer instruction: can the source and destination token accounts belong to the same owner/authority, or be the same account? If YES: does a self-transfer update accounting state (fees credited, rewards claimed, snapshots updated, share ratios changed) without net token movement? Flag as FINDING. Note: this check targets accounting manipulation from self-transfers, distinct from the account key uniqueness validation in ACCOUNT_VALIDATION.md's Self-Transfer Risk column.
For protocols handling multiple token types:
Check: If instruction A handles MintX and instruction B handles MintY, can MintX accounts be passed to instruction B's logic?
Can tokens be sent to the protocol's token accounts without calling deposit()?
If YES (almost always YES on Solana):
token_account.amount)If NO:
For EVERY token type the protocol holds, queries, or receives - including SOL lamports:
| Token Type | Can Transfer To Protocol? | Changes Accounting? | Blocks Operations? | Triggers Side Effects? | |------------|--------------------------|--------------------|--------------------|----------------------| | SOL (lamports) | YES (always) | YES/NO | YES/NO | YES/NO | | {spl_token_a} | YES/NO | YES/NO | YES/NO | YES/NO |
RULE: If ANY transferable token affects state -> analyze: accounting divergence, rent impact, operation blocking, side effect chains.
For each token identified:
| Token | Entry Points | Exit Points | Tracking Var | token_account.amount Used? | Unsolicited Possible? | |-------|--------------|-------------|--------------|---------------------------|----------------------| | [Name/Mint] | deposit, CPI return | withdraw, claim | total_deposited | YES/NO | YES/NO |
For protocols with multiple tokens:
For every CPI call that returns tokens or modifies accounts:
Common mismatches:
Check: invoke_signed(&instruction, &[accounts...]) - verify the target program and returned account state match expectations.
For every CPI transfer to external programs:
| Token / Mint | On Transfer Side Effect | Impact on Protocol | |--------------|------------------------|-------------------| | [Token] | TransferHook executes arbitrary CPI | Potential reentrancy / state corruption | | [Token] | TransferFee withholds portion | Accounting mismatch (sent != received) | | [Token] | PermanentDelegate can move tokens | Tokens can leave without protocol consent |
| CPI Call / Event | Side Effect | Token Type Produced | Protocol Handles This Type? | Mismatch? | |------------------|-------------|--------------------|-----------------------------|-----------| | {cpi_call} | {side_effect} | {token_type_or_UNKNOWN} | YES/NO | YES/NO |
RULES: Side effect type != expected -> FINDING. Type UNKNOWN -> CONTESTED (Rule 4). Check BOTH CPI calls AND unsolicited transfers.
// RED FLAG: Direct balance usage - donatable
let rate = ctx.accounts.vault_token.amount / vault.total_shares;
// BETTER: Tracked balance - but verify total_deposited updated on ALL entry paths
let rate = vault.total_deposited / vault.total_shares;
When this skill identifies an issue:
**ID**: [TF-N]
**Severity**: [based on fund impact]
**Step Execution**: S1,2,3,4,5,6,7,8,9 | X(reasons) | ?(uncertain)
**Location**: program/src/instructions/file.rs:LineN
**Title**: [Token type] can enter/exit via [path] without [expected accounting update]
**Description**: [Trace the token flow and where it diverges from expected]
**Impact**: [What breaks: exchange rates, user balances, protocol insolvency]
CRITICAL: You MUST report completion status for ALL sections. Findings with incomplete sections will be flagged for depth review.
| Section | Required | Completed? | Notes | |---------|----------|------------|-------| | 1. Token Entry Points | YES | Y/X/? | | | 2. Token State Tracking | YES | Y/X/? | | | 3. Token Exit Points | YES | Y/X/? | | | 4. Token Type Separation | IF multi-token | Y/X(N/A)/? | | | 5. Unsolicited Transfer Analysis | YES | Y/X/? | | | 5b. Unsolicited Transfer Matrix (All Types) | YES | Y/X/? | MANDATORY - never skip | | 6. Token Flow Checklist | YES | Y/X/? | | | 7. Cross-Token Interactions | IF multi-token | Y/X(N/A)/? | | | 8. CPI Return Type Verification | YES | Y/X/? | MANDATORY - never skip | | 9. Transfer Side Effects (Token-2022) | YES | Y/X/? | MANDATORY - never skip | | 9d. Side Effect Token Type | YES | Y/X/? | MANDATORY - never skip |
TOKEN_2022_EXTENSIONS.md for TransferHook/TransferFee. IF program ID UNVERIFIED -> mark CONTESTED.Sections 8 and 9 MUST produce tabular output even if uncertain. If UNVERIFIED: verdict cannot be REFUTED, use CONTESTED. If side effects UNKNOWN: apply adversarial default and document assumptions.
development
Prepare Solidity projects for a security audit — test coverage, test quality, NatSpec docs, code hygiene, dependency health, best-practice enforcement, deployment readiness, and project documentation checks. Generates a scored Audit Readiness Report and optionally runs static analysis. Trigger on: "prepare for audit", "audit readiness", "pre-audit check", "audit prep", "NatSpec check", or any request to review a Solidity codebase before a security review.
development
Launch the Plamen deterministic Web3 security audit pipeline
development
Run the Plamen smart-contract audit wizard in Codex
testing
Launch the Plamen deterministic L1 infrastructure audit pipeline