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

V4 Hook Delta Accounting

skill-omermaksutii-rugproof-v4-hook-delta-accounting · by omermaksutii

Detect Uniswap V4 hooks that fail to settle currency deltas with the PoolManager. Every credit/debit a hook creates (BeforeSwapDelta, afterSwap hookDelta, take/mint, donate, settle/sync) is tracked in the manager's transient nonzeroDeltaCount; if the books aren't flat when unlock returns, the whole transaction reverts (CurrencyNotSettled), and mismatched take/settle/donate either strands hook fun…

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

Install

$ agentstack add skill-omermaksutii-rugproof-v4-hook-delta-accounting

✓ 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-omermaksutii-rugproof-v4-hook-delta-accounting)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
2mo 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 Hook Delta Accounting? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Uniswap V4 hook delta-accounting detection

When this applies

Trigger on any of:

  • Callbacks returning BeforeSwapDelta or a non-zero int128 hookDelta from afterSwap/afterAddLiquidity/afterRemoveLiquidity
  • Calls to poolManager.take, settle, sync, mint, burn, donate, clear
  • Custom unlockCallback that moves currency in/out of the manager
  • Hooks that charge custom fees, skim, or rebate by adjusting deltas
  • currencyDelta reads, or accounting that must net to zero before unlock returns
  • Donations to a pool, or take/settle pairs that should balance

Detection patterns

Hook takes currency but never settles (HIGH)

function afterSwap(address, PoolKey calldata key, ..., BalanceDelta, bytes calldata)
    external override returns (bytes4, int128)
{
    poolManager.take(key.currency0, address(this), feeAmount);  // ← creates a -debt for the hook
    return (this.afterSwap.selector, 0);                         // ← returns 0 delta, never settles
}

take debits the hook's currency balance in the manager; with no matching settle/returned delta, nonzeroDeltaCount != 0 and the entire unlock reverts CurrencyNotSettled — every swap on the pool reverts. Signal: take/mint without a balancing settle/burn or a non-zero returned hookDelta accounting for it.

Returned delta not backed by a real transfer (HIGH)

return (this.afterSwap.selector, int128(feeAmount));   // claims to owe the pool feeAmount...
// ...but the hook never `sync` + `settle`s those tokens into the manager

A positive hookDelta says "the hook owes the pool X"; if the hook never actually transfers and settles X, the books don't flatten → revert, or in the inverse direction the swapper leaves with unpaid debt. Signal: non-zero returned delta with no corresponding sync/settle (or take) of the same currency/amount.

Donate / take imbalance (HIGH)

poolManager.donate(key, amount0, amount1, "");  // adds to pool reserves...
// hook forgot to settle the donated tokens it owes

donate increases what the hook owes the pool; the tokens must be settled. Imbalanced donate strands funds or reverts. Signal: donate without settling the donated amounts, or take of donated funds with no offsetting credit.

BeforeSwapDelta sign/units error (HIGH)

BeforeSwapDelta d = toBeforeSwapDelta(int128(amtSpecified), 0);  // wrong: specified vs unspecified swapped

BeforeSwapDelta packs (specified, unspecified) deltas; swapping the two halves or the sign mis-accounts the swap and either reverts or hands the swapper free output. Signal: toBeforeSwapDelta arguments in the wrong slot/sign, or specified-delta not reconciled with the actual swap amount.

Severity rubric

| Pattern | Severity | Notes | |---|---|---| | take/mint with no matching settle → CurrencyNotSettled | High | Pool-wide swap DoS | | Returned hookDelta not backed by settle → revert or free funds | High | Loss or DoS | | Donate without settling owed tokens | High | Stranded funds / revert | | BeforeSwapDelta sign/slot error | High | Mis-accounted swap, value leak | | Hook over-settles (pays more than owed) | Medium | Hook self-loss, no swapper gain | | Deltas always net to zero within callback | Info | Correct accounting |

Remediation patterns

  1. Net every delta to zero before unlock returns — for each currency the hook touches, pair take with settle (or a correct returned hookDelta).
  2. sync → transfer → settle — call poolManager.sync(currency), transfer the tokens in, then settle() so the manager credits the exact owed amount.
  3. Use the official delta helperstoBeforeSwapDelta(specified, unspecified) with correct argument order and signs; reconcile specified against params.amountSpecified.
  4. Assert flatness in tests — after a swap, assert poolManager.currencyDelta(hook, currency) == 0 for every currency.
  5. Settle donations — every donate must be followed by transferring + settling the donated amounts.

False-positive notes

  • A hook returning BeforeSwapDeltaLibrary.ZERO_DELTA / 0 hookDelta and never calling take/settle/donate has nothing to settle — Info.
  • Settlement done inside a shared internal helper called at the end of the callback may look unbalanced locally — trace the full callback before flagging.
  • Over-settling (hook pays extra) is a hook self-loss, not a protocol-loss — Medium, not High.

Related

  • [[v4-hook-permission-flags-mismatch]] — returnDelta flags must be set for deltas to apply
  • [[v4-hook-reentrancy-via-unlock]] — settlement ordering vs. reentrancy
  • [[unchecked-calls]]

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.