Systematic review of DeFi protocols on Solana covering AMM invariants, lending safety, oracle manipulation, flash loan vectors, and liquidation logic
curl -s https://parity.cx/api/skills/defi-review | shcopyYou are performing a specialized security review of a DeFi protocol on Solana. This skill extends the base security-audit with domain-specific checks for financial primitives: AMM constant-product invariants, lending collateral ratios, oracle price manipulation vectors, flash loan attack surfaces, and liquidation logic correctness.
| Source | Path | Contains |
|--------|------|----------|
| Vulnerability Rules | programs/parity/src/context_engine.rs > VULNERABILITY_RULES | Base pattern database |
| Curated Audit Findings | programs/parity/src/context_engine.rs > CURATED_AUDIT_FINDINGS | Real DeFi vulnerabilities from public audits |
| Security Audit Skill | skills/security-audit/SKILL.md | Base security checks (run these first) |
| Token Analyzer Skill | skills/token-analyzer/SKILL.md | Token-specific checks for SPL/Token-2022 interactions |
GitHub base URL: https://github.com/paritydotcx/Skills/blob/main/
Identify the protocol type by analyzing instruction handlers and account structures:
swap, add_liquidity, remove_liquidity instructions, pool accounts with reserve balances, LP token mintsdeposit, borrow, repay, liquidate instructions, collateral accounts, interest rate calculationsstake, unstake, claim_rewards instructions, stake pool accounts, reward distribution logicdeposit, withdraw with share-based accounting, strategy executionopen_position, close_position, add_margin, oracle price feeds, funding rate calculationsClassify the protocol and apply the relevant domain-specific checks below.
If the protocol uses external price data, verify:
AccountInfo that could be substituted with attacker-controlled data.confidence / price > threshold (typically 2-5%).- Price is read from an AMM pool's reserve ratio (not an oracle)
- No TWAP or multi-block averaging is used
- The price influences a high-value operation (liquidation, borrowing, swap)
Vulnerable pattern:
// VULNERABLE: reads pool reserves as price, manipulable via flash loan
let price = pool.reserve_a as u128 * PRECISION / pool.reserve_b as u128;Secure pattern:
// SECURE: Pyth oracle with staleness and confidence checks
let price_feed = ctx.accounts.oracle.load_price_feed()?;
let current_price = price_feed.get_price_no_older_than(clock.unix_timestamp, MAX_ORACLE_AGE)?;
require!(
current_price.conf as u64 * 100 / current_price.price.unsigned_abs() < MAX_CONFIDENCE_PCT,
ErrorCode::OraclePriceUnreliable
);Finding if violated:
For AMM/DEX protocols, verify:
k = x * y is maintained after every swap. The new reserves must satisfy new_x * new_y >= old_x * old_y (allowing for fees).minimum_amount_out parameter. Without it, sandwich attacks extract value from every swap.Finding if violated:
For lending protocols, verify:
Finding if violated:
Analyze whether any operation can be exploited within a single transaction:
- Read pool reserves, manipulate with flash loan, execute swap at manipulated price, repay flash loan
- Read collateral value, inflate via flash loan deposit, borrow against inflated value, withdraw collateral
Finding if applicable:
If the protocol has liquidation:
Finding if violated:
Check protocol-wide invariants that must always hold:
Identify whether these invariants are enforced on-chain or only implicitly assumed.
Finding if violated:
| Severity | Penalty per finding |
|----------|-------------------|
| Critical | -25 |
| High | -15 |
| Medium | -8 |
| Info | -3 |
Start at 100. Subtract penalties. Floor at 0.
{
"score": 38,
"defi_surface": {
"protocol_type": "lending",
"oracle_type": "pyth",
"has_flash_loan": false,
"has_liquidation": true,
"token_standard": "spl-token",
"attack_vectors_identified": ["oracle_staleness", "partial_liquidation_missing"]
},
"findings": [
{
"severity": "critical",
"title": "Oracle price staleness not enforced in borrow instruction",
"location": { "file": "lib.rs", "line": 134, "instruction": "borrow" },
"description": "The Pyth price feed is read without a staleness check. An attacker could borrow against a stale price during high volatility.",
"recommendation": "Add get_price_no_older_than(clock.unix_timestamp, 30) to reject prices older than 30 seconds."
}
],
"summary": "Lending protocol with 2 critical (oracle, collateral ratio), 1 high (liquidation). Flash loan surface: low (no pool-based pricing). Primary risk: oracle manipulation during borrow."
}