skills/protocol-patterns/amm-dex/SKILL.md
AMM and DEX security patterns covering pricing, LP accounting, MEV, and swap invariants.
npx skillsauth add apegurus/solidity-argus amm-dexInstall 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.
AMMs (Uniswap, Curve, Balancer) enable permissionless token swaps via liquidity pools. Core security concerns: price manipulation, MEV, impermanent loss, and LP token accounting.
┌─────────────────────────────────────────────────────────────┐
│ AMM POOL │
├─────────────────────────────────────────────────────────────┤
│ │
│ x * y = k (Constant Product) │
│ │
│ ┌─────────┐ ┌─────────┐ │
│ │ Token A │ ◄─────► │ Token B │ │
│ │ Reserve │ │ Reserve │ │
│ └─────────┘ └─────────┘ │
│ ▲ ▲ │
│ │ │ │
│ ┌─────────────────────────────┐ │
│ │ LP Token Holders │ │
│ └─────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Attack Vectors:
Checklist:
// VULNERABLE: Spot price for external use
function getPrice() external view returns (uint256) {
return reserve1 * 1e18 / reserve0; // Manipulatable!
}
// SECURE: Accumulator-based TWAP
function updateTWAP() internal {
uint32 timeElapsed = block.timestamp - lastUpdate;
if (timeElapsed > 0) {
priceAccumulator += getSpotPrice() * timeElapsed;
lastUpdate = block.timestamp;
}
}
Attack Vectors:
Checklist:
// VULNERABLE: No deadline check
function swap(uint256 amountIn, uint256 minAmountOut) external {
// Missing deadline check - tx can be held and executed later
}
// SECURE
function swap(
uint256 amountIn,
uint256 minAmountOut,
uint256 deadline
) external {
require(block.timestamp <= deadline, "Expired");
// ...
require(amountOut >= minAmountOut, "Slippage");
}
Attack Vectors:
Checklist:
// Uniswap V2 first deposit protection
uint256 public constant MINIMUM_LIQUIDITY = 1000;
function mint() external returns (uint256 liquidity) {
uint256 _totalSupply = totalSupply;
if (_totalSupply == 0) {
liquidity = Math.sqrt(amount0 * amount1) - MINIMUM_LIQUIDITY;
_mint(address(0), MINIMUM_LIQUIDITY); // Lock minimum
} else {
liquidity = Math.min(
amount0 * _totalSupply / _reserve0,
amount1 * _totalSupply / _reserve1
);
}
}
Attack Vectors:
Checklist:
// VULNERABLE: k can decrease due to rounding
function swap(uint256 amountIn, uint256 amountOut) external {
// ... transfer tokens ...
require(reserve0 * reserve1 >= k, "Invalid k"); // Should be >=
}
Attack Vectors:
Checklist:
// Curve's virtual_price can be manipulated during reentrancy
// Attack: Enter pool → in callback, read virtual_price → it's wrong
// VULNERABLE: Reading Curve virtual_price during callback
function deposit(uint256 amount) external {
uint256 price = curvePool.get_virtual_price(); // Can be manipulated
uint256 value = amount * price / 1e18;
}
Additional concerns:
Additional concerns:
testing
Specialist profile for mechanically applying the attack-vector deck and classifying vectors as skip, drop, or investigate.
tools
Specialist profile for libraries, helpers, base contracts, adapters, encoders, wrappers, and integration glue.
testing
Specialist profile for rounding, scale, decimal, downcast, and arithmetic accounting edge cases.
testing
Specialist profile for extracting conservation laws and state couplings, then searching for violating paths.