Skip to content

Arbitrum One·Scanned 04 Nov 2026, 13:34 UTC

Contract report

0x90a99a9c0b2fe748e6600dc4a9a8b814292428c0

Verdict

Caution

50/100 safety

Unverified Uniswap v4 hook: a pauser role can likely freeze swaps in 19+ USDC pools; admin looks like a timelock

This is a Uniswap v4 hook on Arbitrum that runs on every swap in 19+ USDC pools, and its source code is not published, so nobody can check what it really does. A separate pauser address can likely freeze trading in all of those pools, and admin roles can change fee settings, the fee recipient and pull tokens held by the hook. On the plus side, the code cannot be upgraded, the top admin appears to be a timelock, and the hook cannot stop liquidity providers from withdrawing.

Score breakdown

  • Contract
    50
  • Token
    n/a
  • Social / X
    n/a
  • Website
    n/a

Token: not assessed (not a token)

Higher is safer · 0 = worst · 100 = best

Unknown
—
—

Key findings

  • HighUnknown (unverified bytecode) can change fees
  • HighUnknown (unverified bytecode) can pause the contract
  • HighUnknown (unverified bytecode) can pause the contract
  • MediumUnverified Uniswap v4 hook on the swap path
  • GoodTop admin appears to be a timelock, delaying role changes

What would change the verdict

  • Raises safety:Hook source gets verified and shows pause() cannot block swaps or that fees are capped → up
  • Raises safety:PAUSER_ROLE moves behind the timelock or a known multisig → up
  • Lowers safety:Pauser calls pause() and swaps in the attached pools start reverting → down
  • Lowers safety:Admin grants a role to a fresh wallet or raises protocol share / redirects the fee recipient → down
View on explorer ↗

Findings

10 findings

Risks (7)

  • HighUnknown (unverified bytecode) can change feesfeesDeterministic

    setFeeTier(uint24,int24) (unknown (unverified bytecode)): Can change fees / taxes / fee split [selector 0x10a27fd8]. Fees can be raised after people buy, turning sells into a loss or a de-facto honeypot.

    Evidence

    • staticprivilege setFeeTier(uint24,int24) restricted to unknown (unverified bytecode)
      Show source
      Can change fees / taxes / fee split [selector 0x10a27fd8]

    Confirmed by: facts

  • HighUnknown (unverified bytecode) can pause the contractpauseDeterministic

    unpause() (unknown (unverified bytecode)): can pause the contract's functions (e.g. deposits, payments or withdrawals).

    Evidence

    • staticprivilege unpause() restricted to unknown (unverified bytecode)
      Show source
      Can pause / freeze all transfers [selector 0x3f4ba83a]

    Confirmed by: facts

  • HighUnknown (unverified bytecode) can pause the contractpauseDeterministic

    pause() (unknown (unverified bytecode)): can pause the contract's functions (e.g. deposits, payments or withdrawals).

    Evidence

    • staticprivilege pause() restricted to unknown (unverified bytecode)
      Show source
      Can pause / freeze all transfers [selector 0x8456cb59]
    • on-chainCurrent role holders: PAUSER_ROLE=0xffD92e9A1192a7d2E3cB6f6c9491A054dEA0939e
      Show source
      PAUSER_ROLE=0xffD92e9A1192a7d2E3cB6f6c9491A054dEA0939e
    • on-chainhook permissions (from address bits) = beforeInitialize, beforeAddLiquidity, beforeSwap, afterSwap
      Show source
      beforeInitialize, beforeAddLiquidity, beforeSwap, afterSwap

    Confirmed by: facts, claude-opus-5.5

  • MediumUnverified Uniswap v4 hook on the swap pathhidden-functionDeterministic

    This contract is a Uniswap v4 hook with beforeInitialize, beforeAddLiquidity, beforeSwap, afterSwap permissions, but its source code is not verified. The PoolManager runs this code on every swap in each pool that uses it. Without source, nobody can check whether it blocks sells or takes extra fees.

    Evidence

    • on-chainhook address 0x90a99a9c0B2Fe748e6600dc4A9A8b814292428C0 permission bits: beforeInitialize, beforeAddLiquidity, beforeSwap, afterSwap
    • on-chaincontract.verified = false; isProxy = false
      Show source
      "verified": false

    Confirmed by: facts, claude-opus-5.5, grok-4.7

  • MediumSource code is not verifiedotherDeterministic

    The contract source is not published on the explorer, so nobody can read what it really does. The analysis relies on bytecode only.

    Evidence

    • on-chainexplorer: no verified source for 0x90a99a9c0B2Fe748e6600dc4A9A8b814292428C0

    Confirmed by: facts

  • MediumUnknown (unverified bytecode) can change feesfeesDeterministic

    setProtocolFeeRecipient(address) (unknown (unverified bytecode)): Can redirect where fees/funds go or who operates the contract [selector 0xe521cb92]. Fees can be raised after people buy, turning sells into a loss or a de-facto honeypot.

    Evidence

    • staticprivilege setProtocolFeeRecipient(address) restricted to unknown (unverified bytecode)
      Show source
      Can redirect where fees/funds go or who operates the contract [selector 0xe521cb92]

    Confirmed by: facts

  • MediumFour separate addresses hold admin, operator, pauser and unnamed rolesownershipAI

    Roles on the hook are split across four addresses: - DEFAULT_ADMIN_ROLE: 0xD4eB…1878. This holder can grant or revoke every role. - OPERATOR_ROLE: 0x80E5…f999. - PAUSER_ROLE: 0xffD9…939e. - An unnamed role 0xe2f4eaae…: 0x9BB9…873D. Which functions each role gates, and whether the three non-admin holders are wallets or contracts, is unknown.

    Evidence

    • on-chainCurrent role holders: 0xe2f4eaae4a9751e85a3e4a7b9587827a877f29914755229b07a7b2da98285f70=0x9BB99169859f62D8b36879e09f4F10F95A35873D, OPERATOR_ROLE=0x80E5D67193E5dD897C4BFE7eC262F3f3e6F3f999, DEFAULT_ADMIN_ROLE=0xD4eB46BdD6F6845171D270216CC5b067Aa551878, PAUSER_ROLE=0xffD92e9A1192a7d2E3cB6f6c9491A054dEA0939e
      Show source
      DEFAULT_ADMIN_ROLE=0xD4eB46BdD6F6845171D270216CC5b067Aa551878

    Confirmed by: claude-opus-5.5, grok-4.7

Positive signals (1)

  • PositiveTop admin appears to be a timelock, delaying role changesownershipAI

    The DEFAULT_ADMIN_ROLE holder and owner, 0xD4eB…1878, exposes schedule/execute/cancel/updateDelay/PROPOSER_ROLE/EXECUTOR_ROLE/CANCELLER_ROLE. That matches an OpenZeppelin-style TimelockController. If so, role grants by the admin are announced in advance and delayed. The delay length and the proposers/executors are unknown because the contract is unverified. The timelock also does not cover the separate PAUSER_ROLE holder.

    Evidence

    • on-chainowner() = 0xD4eB46BdD6F6845171D270216CC5b067Aa551878
      Show source
      "owner": "0xD4eB46BdD6F6845171D270216CC5b067Aa551878"

    Confirmed by: claude-opus-5.5, grok-4.7

Notes (2)

  • InfoHook cannot block liquidity withdrawals or skim swap amountsliquidityAI

    The address permission bits enable only beforeInitialize, beforeAddLiquidity, beforeSwap and afterSwap. Without beforeRemoveLiquidity, the hook cannot stop LPs from withdrawing liquidity from the PoolManager. Without any *ReturnDelta flags, it cannot skim swap or LP amounts through deltas. It can still block new liquidity additions and swaps.

    Evidence

    • on-chainhook permissions (from address bits) = beforeInitialize, beforeAddLiquidity, beforeSwap, afterSwap
      Show source
      fixed by the hook address — cannot change after deployment

    Confirmed by: claude-opus-5.5, grok-4.7

  • InfoDeployed via standard CREATE2 deployer with no retained controlotherAI

    The creator, 0x4e59…956C, is the widely used deterministic CREATE2 deployer. It is commonly used to mine v4 hook addresses with the right permission bits and gives the factory no ongoing control. The transaction sender was 0x7E61…730D. Blockscout labels the hook reputation=ok, is_scam=false.

    Evidence

    • on-chainCreated by factory contract 0x4e59b44847b379578588920cA78FbF26c0B4956C; tx sender 0x7E61A5EbCCd26d9D91690C6037d7224F5384730D
      Show source
      Created by factory contract 0x4e59b44847b379578588920cA78FbF26c0B4956C
    • on-chainexplorer: blockscout isScam=false reputation=ok
      Show source
      is_scam=false, reputation=ok

    Confirmed by: claude-opus-5.5, grok-4.7

Score breakdown

Higher is safer. The overall is the weighted average of the assessed parts, then capped by hard facts.

  • Contract

    weight 45%
    50
    Capped · max 60

    source code not verified → max 60

    The hook is not upgradeable and its top admin looks like a timelock, but its source is unverified and separate role holders can likely pause swaps and change fees across 19+ pools.

    Why this score

    Raised the score

    • Not a proxy, so the hook code cannot be replaced
    • Top admin appears to be a timelock contract
    • Permission bits rule out blocking liquidity removal or skimming swap amounts
    • Blockscout reputation ok, not flagged as scam

    Lowered the score

    • Source code not verified, no static analysis possible
    • Pause/unpause on the swap path held by a separate pauser address
    • Fee tier, protocol share and fee recipient can be changed
    • Admins can rescue tokens held by the hook
    • Four role holders with unclear powers
  • Token

    weight 30%
    —
    Not assessed

    Not enough data — excluded from the overall score.

  • Social / X

    weight 15%
    —
    Not assessed

    Not enough data — excluded from the overall score.

  • Website

    weight 10%
    —
    Not assessed

    Not enough data — excluded from the overall score.