AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

V4 Security Foundations

skill-uniswap-uniswap-ai-v4-security-foundations · by Uniswap

Security-first Uniswap v4 hook development. Use when user mentions "v4 hooks", "hook security", "PoolManager", "beforeSwap", "afterSwap", or asks about V4 hook best practices, vulnerabilities, or audit requirements.

No reviews yet
0 installs
1 views
0.0% view→install

Install

$ agentstack add skill-uniswap-uniswap-ai-v4-security-foundations

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-uniswap-uniswap-ai-v4-security-foundations)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of V4 Security Foundations? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

v4 Hook Security Foundations

Security-first guide for building Uniswap v4 hooks. Hook vulnerabilities can drain user funds—understand these concepts before writing any hook code.

Threat Model

Before writing code, understand the v4 security context:

| Threat Area | Description | Mitigation | | ----------------------- | ---------------------------------------------------------- | ---------------------------------------------- | | Caller Verification | Only PoolManager should invoke hook functions | Verify msg.sender == address(poolManager) | | Sender Identity | msg.sender always equals PoolManager, never the end user | Use sender parameter for user identity | | Router Context | The sender parameter identifies the router, not the user | Implement router allowlisting | | State Exposure | Hook state is readable during mid-transaction execution | Avoid storing sensitive data on-chain | | Reentrancy Surface | External calls from hooks can enable reentrancy | Use reentrancy guards; minimize external calls |

Permission Flags Risk Matrix

All 14 hook permissions with associated risk levels:

| Permission Flag | Risk Level | Description | Security Notes | | --------------------------------- | ---------- | --------------------------- | ----------------------------- | | beforeInitialize | LOW | Called before pool creation | Validate pool parameters | | afterInitialize | LOW | Called after pool creation | Safe for state initialization | | beforeAddLiquidity | MEDIUM | Before LP deposits | Can block legitimate LPs | | afterAddLiquidity | LOW | After LP deposits | Safe for tracking/rewards | | beforeRemoveLiquidity | HIGH | Before LP withdrawals | Can trap user funds | | afterRemoveLiquidity | LOW | After LP withdrawals | Safe for tracking | | beforeSwap | HIGH | Before swap execution | Can manipulate prices | | afterSwap | MEDIUM | After swap execution | Can observe final state | | beforeDonate | LOW | Before donations | Access control only | | afterDonate | LOW | After donations | Safe for tracking | | beforeSwapReturnDelta | CRITICAL | Returns custom swap amounts | NoOp attack vector | | afterSwapReturnDelta | HIGH | Modifies post-swap amounts | Can extract value | | afterAddLiquidityReturnDelta | HIGH | Modifies LP token amounts | Can shortchange LPs | | afterRemoveLiquidityReturnDelta | HIGH | Modifies withdrawal amounts | Can steal funds |

Risk Thresholds

  • LOW: Unlikely to cause fund loss
  • MEDIUM: Requires careful implementation
  • HIGH: Can cause fund loss if misimplemented
  • CRITICAL: Can enable complete fund theft

CRITICAL: NoOp Rug Pull Attack

The BEFORE_SWAP_RETURNS_DELTA permission (bit 10) is the most dangerous hook permission. A malicious hook can:

  1. Return a delta claiming it handled the entire swap
  2. PoolManager accepts this and settles the trade
  3. Hook keeps all input tokens without providing output
  4. User loses entire swap amount

Attack Pattern

// MALICIOUS - DO NOT USE
function beforeSwap(
    address,
    PoolKey calldata,
    IPoolManager.SwapParams calldata params,
    bytes calldata
) external override returns (bytes4, BeforeSwapDelta, uint24) {
    // Claim to handle the swap but steal tokens
    int128 amountSpecified = int128(params.amountSpecified);
    BeforeSwapDelta delta = toBeforeSwapDelta(amountSpecified, 0);
    return (BaseHook.beforeSwap.selector, delta, 0);
}

Detection

Before interacting with ANY hook that has beforeSwapReturnDelta: true:

  1. Audit the hook code - Verify legitimate use case
  2. Check ownership - Is it upgradeable? By whom?
  3. Verify track record - Has it been audited by reputable firms?
  4. Start small - Test with minimal amounts first

Legitimate Uses

NoOp patterns are valid for:

  • Just-in-time liquidity (JIT)
  • Custom AMM curves
  • Intent-based trading systems
  • RFQ/PMM integrations

But each requires careful implementation and audit.

Delta Accounting Fundamentals

v4 uses a credit/debit system through the PoolManager:

Core Invariant

For every transaction: sum(deltas) == 0

The PoolManager tracks what each address owes or is owed. At transaction end, all debts must be settled.

Key Functions

| Function | Purpose | Direction | | ---------------------------- | ----------------------------------- | ---------------------- | | take(currency, to, amount) | Withdraw tokens from PoolManager | You receive tokens | | settle(currency) | Pay tokens to PoolManager | You send tokens | | sync(currency) | Update PoolManager balance tracking | Preparation for settle |

Settlement Pattern

// Correct pattern: sync before settle
poolManager.sync(currency);
currency.transfer(address(poolManager), amount);
poolManager.settle(currency);

Common Mistakes

  1. Forgetting sync: Settlement fails without sync
  2. Wrong order: Must sync → transfer → settle
  3. Partial settlement: Leaves transaction in invalid state
  4. Double settlement: Causes accounting errors

Access Control Patterns

PoolManager Verification

Every hook callback MUST verify the caller:

modifier onlyPoolManager() {
    require(msg.sender == address(poolManager), "Not PoolManager");
    _;
}

function beforeSwap(
    address sender,
    PoolKey calldata key,
    IPoolManager.SwapParams calldata params,
    bytes calldata hookData
) external override onlyPoolManager returns (bytes4, BeforeSwapDelta, uint24) {
    // Safe to proceed
}

Why This Matters

Without this check:

  • Anyone can call hook functions directly
  • Attackers can manipulate hook state
  • Funds can be drained through fake callbacks

Router Verification Patterns

The sender parameter is the router, not the end user. For hooks that need user identity:

Allowlisting Pattern

mapping(address => bool) public allowedRouters;

function beforeSwap(
    address sender,  // This is the router
    PoolKey calldata key,
    IPoolManager.SwapParams calldata params,
    bytes calldata hookData
) external override onlyPoolManager returns (bytes4, BeforeSwapDelta, uint24) {
    require(allowedRouters[sender], "Router not allowed");
    // Proceed with swap
}

User Identity via hookData

function beforeSwap(
    address sender,
    PoolKey calldata key,
    IPoolManager.SwapParams calldata params,
    bytes calldata hookData
) external override onlyPoolManager returns (bytes4, BeforeSwapDelta, uint24) {
    // Decode user address from hookData (router must include it)
    address user = abi.decode(hookData, (address));
    // CAUTION: Router must be trusted to provide accurate user
}

msg.sender Trap

// WRONG - msg.sender is always PoolManager in hooks
function beforeSwap(...) external {
    require(msg.sender == someUser); // Always fails or wrong
}

// CORRECT - Use sender parameter
function beforeSwap(address sender, ...) external {
    require(allowedRouters[sender], "Invalid router");
}

Token Handling Hazards

Not all tokens behave like standard ERC-20s:

| Token Type | Hazard | Mitigation | | ------------------- | ------------------------------------ | ----------------------------------- | | Fee-on-transfer | Received amount = 0.8.24 with EVM target set to cancun or later.

  1. External calls: Each cross-contract call adds ~2,600 gas base cost plus the callee's execution. Batch calls where possible.
  2. String operations: Avoid string manipulation in callbacks; use bytes32 for identifiers.
  3. Redundant reads: Cache poolManager calls — repeated getSlot0() or getLiquidity() reads cost gas each time.

Measuring Gas

# Profile a specific hook callback with Foundry
forge test --match-test test_beforeSwapGas --gas-report

# Snapshot gas usage across all tests
forge snapshot --match-contract MyHookTest

Risk Scoring System

Calculate your hook's risk score (0-33):

| Category | Points | Criteria | | --------------------- | ------ | ---------------------------------------- | | Permissions | 0-14 | Sum of enabled permission risk levels | | External Calls | 0-5 | Number and type of external interactions | | State Complexity | 0-5 | Amount of mutable state | | Upgrade Mechanism | 0-5 | Proxy, admin functions, etc. | | Token Handling | 0-4 | Non-standard token support |

Audit Tier Recommendations

| Score | Risk Level | Recommendation | | ----- | ---------- | ------------------------------ | | 0-5 | Low | Self-audit + peer review | | 6-12 | Medium | Professional audit recommended | | 13-20 | High | Professional audit required | | 21-33 | Critical | Multiple audits required |

Absolute Prohibitions

Never do these things in a hook:

  1. Never trust msg.sender for user identity - It's always PoolManager
  2. Never enable beforeSwapReturnDelta without understanding NoOp attacks
  3. Never store passwords, keys, or PII on-chain
  4. Never use transfer() for ETH - Use call{value:}("")
  5. Never assume token decimals - Always query the token
  6. Never use block.timestamp for randomness
  7. Never hardcode gas limits in calls
  8. Never ignore return values from external calls
  9. Never use tx.origin for authorization - It's a phishing vector; malicious contracts can relay calls with the original user's tx.origin

Pre-Deployment Audit Checklist

| # | Item | Required For | | --- | ----------------------------------------- | ------------------------ | | 1 | Code review by security-focused developer | All hooks | | 2 | Unit tests for all callbacks | All hooks | | 3 | Fuzz testing with Foundry | All hooks | | 4 | Invariant testing | Hooks with delta returns | | 5 | Fork testing on mainnet | All hooks | | 6 | Gas profiling | All hooks | | 7 | Formal verification | Critical hooks | | 8 | Slither/Mythril analysis | All hooks | | 9 | External audit | Medium+ risk hooks | | 10 | Bug bounty program | High+ risk hooks | | 11 | Monitoring/alerting setup | All production hooks |

See [references/audit-checklist.md](references/audit-checklist.md) for detailed audit requirements.

Production Hook References

Learn from audited, production hooks:

| Project | Description | Notable Security Features | | -------------- | --------------------- | ----------------------------- | | Flaunch | Token launch platform | Multi-sig admin, timelocks | | EulerSwap | Lending integration | Isolated risk per market | | Zaha TWAMM | Time-weighted AMM | Gradual execution reduces MEV | | Bunni | LP management | Concentrated liquidity guards |

External Resources

Official Documentation

Security Resources

Community


Additional References

  • [Base Hook Template](references/base-hook-template.md) - Complete implementation starter
  • [Vulnerabilities Catalog](references/vulnerabilities-catalog.md) - Common patterns and mitigations
  • [Audit Checklist](references/audit-checklist.md) - Detailed pre-deployment checklist

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.