Likely custom pricing hook on Polygon

Uniswap v4 Hook Contract 0xc9987661b047cd73e3b0d66b2b7615a2ca811088 on Polygon · Custom pricing

Volume (24h)
$0
Value locked (TVL)
$0
All-time volume
$0
Pools using this hook
89
Swaps (24h)
0 (0 traders)
Total swaps
4

What it does

A pool-registering hook that, on swaps, can take over the swap through a before-swap return delta, with an owner who can set pool fees and execute arbitrary calls from the hook.

How it works step by step

  • Registers each pool at initialization: afterInitialize writes to a pool mapping and a pool list, which is exposed through getPoolCount, allPools(uint256) and pools(bytes32).
  • Intercepts swaps in beforeSwap and can return a delta, so the hook may handle part or all of the swap amount itself instead of the pool's normal pricing. The function reads a mapping(address => bool), which looks like an allowlist or a flag per address.
  • Exposes an unlockCallback, so the hook interacts with the pool manager through the unlock pattern, probably to settle or take tokens during swap handling.
  • Lets the owner change a pool's fee with setPoolFee(bytes32,uint24), and there is also a setter for a uint24 default fee value (selector 0xbefa61d5).
  • Includes an owner-only execute(address,uint256,bytes) that makes arbitrary external calls, plus another owner-gated function (0xbfd3da96) that writes an address to slot 5.
Swap behaviour
beforeSwap (0x575e24b4) is nonpayable, reads the pool mapping and an address-to-bool mapping, and, because the beforeSwapReturnDelta permission is on, can return a delta that shifts the swap amounts to the hook. The exact pricing and settlement logic cannot be determined from the decoded output. There is no afterSwap permission.
Liquidity behaviour
No liquidity callbacks. The liquidity-related functions in the dispatch table are stubs for the unused hook interface and are not enabled in the permissions.
Fee behaviour
The owner can set a fee per pool through setPoolFee(bytes32,uint24) and can change a stored uint24 value, probably a default fee. How the fee is applied to swaps, and whether the hook takes it through the return delta, cannot be confirmed without source.
Owner & admin controls
A single owner (slot 0, setOwner(address), owner()) can transfer ownership, set per-pool fees via setPoolFee, change a uint24 value via 0xbefa61d5, call execute(address,uint256,bytes) to make arbitrary calls, and set an address in slot 5 via 0xbfd3da96. No timelock, pause or proxy pattern was seen in the decoded output.

Enabled Uniswap v4 callbacks

afterInitialize, beforeSwap, beforeSwapReturnDelta

afterInitialize registers the new pool in the hook's pool storage and list. beforeSwap runs custom swap logic and, with beforeSwapReturnDelta, can adjust the swap's token amounts so the hook takes or supplies part of the trade.

Security & trust assessment

Risk level: high, estimated (decoded bytecode, low confidence).

Who controls it: The owner can set pool fees, change configuration, and run arbitrary calls from the hook, and could redirect any funds or approvals the hook holds. The owner can also hand control to another address immediately.

Risk to user funds: The hook can take or settle tokens through the unlock callback and beforeSwap return delta, so it may hold balances temporarily or persistently. The owner's execute function could move those balances. Swaps could also be blocked or made costly through the owner-controlled fee or custom swap logic, but a pause switch was not seen.

Security findings

  • [high] Arbitrary call execution by owner: execute(address,uint256,bytes) is gated by the owner slot and lets the owner make any call from the hook's address, so it could move any tokens or approvals the hook holds.
  • [medium] Return-delta swap control: beforeSwapReturnDelta is enabled, so the hook can redirect swap amounts to itself. Whether the delta is bounded or tied to the configured fee cannot be verified from bytecode.
  • [medium] Owner-set pool fees: setPoolFee(bytes32,uint24) is owner-only. No cap was visible in the decoded output, so the fee could possibly be set to a very high value.
  • [medium] Single EOA-style owner with transferable control: setOwner(address) changes ownership in one transaction, with no two-step transfer or timelock visible.
  • [info] Unverified source: No verified source is available, so behaviour is inferred from selectors and storage layout only, and unnamed functions (0x0aa87769, 0x8ec6cd0d, 0xbefa61d5, 0xbfd3da96) have unknown semantics.

Contract details

Verified source
No
Bytecode size
14,739 bytes
Upgradeable proxy
No
Detected patterns
return-delta

Pools using Likely custom pricing hook