defi-amm-security

Security checklist for Solidity AMM contracts, liquidity pools, and swap flows. Covers reentrancy, CEI ordering, donation or inflation attacks, oracle…

INSTALLATION
npx skills add https://github.com/affaan-m/everything-claude-code --skill defi-amm-security
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

$27

Never include secrets, private keys, seed phrases, API tokens, or mainnet signing credentials in command examples, logs, or reports.

Examples

Reentrancy: enforce CEI order

Vulnerable:

function withdraw(uint256 amount) external {

    require(balances[msg.sender] >= amount);

    token.transfer(msg.sender, amount);

    balances[msg.sender] -= amount;

}

Safe:

import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";

import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

using SafeERC20 for IERC20;

function withdraw(uint256 amount) external nonReentrant {

    require(balances[msg.sender] >= amount, "Insufficient");

    balances[msg.sender] -= amount;

    token.safeTransfer(msg.sender, amount);

}

Do not write your own guard when a hardened library exists.

Donation or inflation attacks

Using token.balanceOf(address(this)) directly for share math lets attackers manipulate the denominator by sending tokens to the contract outside the intended path.

// Vulnerable

function deposit(uint256 assets) external returns (uint256 shares) {

    shares = (assets * totalShares) / token.balanceOf(address(this));

}
// Safe

uint256 private _totalAssets;

function deposit(uint256 assets) external nonReentrant returns (uint256 shares) {

    uint256 balBefore = token.balanceOf(address(this));

    token.safeTransferFrom(msg.sender, address(this), assets);

    uint256 received = token.balanceOf(address(this)) - balBefore;

    shares = totalShares == 0 ? received : (received * totalShares) / _totalAssets;

    _totalAssets += received;

    totalShares += shares;

}

Track internal accounting and measure actual tokens received.

Oracle manipulation

Spot prices are flash-loan manipulable. Prefer TWAP.

uint32[] memory secondsAgos = new uint32[](2);

secondsAgos[0] = 1800;

secondsAgos[1] = 0;

(int56[] memory tickCumulatives,) = IUniswapV3Pool(pool).observe(secondsAgos);

int24 twapTick = int24(

    (tickCumulatives[1] - tickCumulatives[0]) / int56(uint56(30 minutes))

);

uint160 sqrtPriceX96 = TickMath.getSqrtRatioAtTick(twapTick);

Slippage protection

Every swap path needs caller-provided slippage and a deadline.

function swap(

    uint256 amountIn,

    uint256 amountOutMin,

    uint256 deadline

) external returns (uint256 amountOut) {

    require(block.timestamp <= deadline, "Expired");

    amountOut = _calculateOut(amountIn);

    require(amountOut >= amountOutMin, "Slippage exceeded");

    _executeSwap(amountIn, amountOut);

}

Safe reserve math

import {FullMath} from "@uniswap/v3-core/contracts/libraries/FullMath.sol";

uint256 result = FullMath.mulDiv(a, b, c);

For large reserve math, avoid naive a * b / c when overflow risk exists.

Admin controls

import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";

contract MyAMM is Ownable2Step {

    function setFee(uint256 fee) external onlyOwner { ... }

    function pause() external onlyOwner { ... }

}

Prefer explicit acceptance for ownership transfer and gate every privileged path.

Security Checklist

  • Reentrancy-exposed entrypoints use nonReentrant
  • CEI ordering is respected
  • Share math does not depend on raw balanceOf(address(this))
  • ERC-20 transfers use SafeERC20
  • Deposits measure actual tokens received
  • Oracle reads use TWAP or another manipulation-resistant source
  • Swaps require amountOutMin and deadline
  • Overflow-sensitive reserve math uses safe primitives like mulDiv
  • Admin functions are access-controlled
  • Emergency pause exists and is tested
  • Static analysis and fuzzing are run before production

Audit Tools

pip install slither-analyzer

slither . --exclude-dependencies

echidna-test . --contract YourAMM --config echidna.yaml

forge test --fuzz-runs 10000
BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card