Robinhood Chain·Scanned 05 Nov 2026, 01:40 UTC
PonsV2LauncherToken $ZHOOK
Verdict
53/100 safety
Token has no owner, mint or blacklist; sells work with 0% token tax plus a 3% pool fee; launch heavily bundled.
The ZHOOK token contract is a clean launchpad template: nobody can mint, freeze or tax it, and test buys and sells worked, with only the pool's frozen 3% trading fee. The main concerns sit around it. Large bundled buys captured much of the supply at launch, and a single Pons protocol owner controls the hook, factory and LP locker, including rescue functions we could not fully review. The website also sells private trading features that the team's own docs and the dApp test show are not live yet. On the positive side, pool liquidity is locked, the deployer holds nothing and has burned about 8% of supply.
Score breakdown
- Contract60
- Token50
- Social / X45
- Website38
Higher is safer · 0 = worst · 100 = best
- Yes
- 0%
- None (no owner role)
- 0% / 100%
- MC at check
- $17.8K
- MC now
- no live price
- Since check
- —
- Liquidity
- $12.7K
Key findings
- HighDApp requests an unlimited token approval to a contract we did not review
- MediumOne protocol owner controls hook, factory, vault and LP locker
- MediumBundled wallets bought a large share of supply at launch
- MediumSite advertises private trading that docs and dApp test show isn't live
- GoodOngoing token burns verified on-chain: 8.0% of supply burned
What would change the verdict
- Raises safety:Pons protocol owner is shown to be a multisig or timelock, or the factory and locker source confirms no rescue or withdraw path → up
- Lowers safety:Owner uses factory rescue functions to move funds from this launch, or the locker releases the LP → down
- Lowers safety:Launch bundle wallets turn out to still hold a large share and start selling → down
Findings
15 findingsRisks (7)
HighDApp requests an unlimited token approval to a contract we did not reviewotherDeterministic
During the "Swap USDG to ETH" flow the dApp asks for an unlimited token approval in favour of an unknown spender, which is not among the contracts we analysed. Prefer approving only the exact amount.
Evidence
- forkdApp test "Swap USDG to ETH" on a local fork (https://dapp.zerohook.trade/)
Show source
wallet no balance change; 1 tx (approve ok). No successful transaction was made for this goal (timeout). | driver: timeout — goal time cap reached - forkapprove(address,uint256) → 0x5fc5360d0400a0fd4f2af552add042d716f1d168 (spender=0x0000…8BA3 (Permit2), value=MAX_UINT256 (unlimited))
- forkdappTests: Swap USDG to ETH step approve
Show source
unlimited approval (unlimited) to 0x0000…8BA3 (Permit2) — known infra: Permit2
Confirmed by: facts, claude-opus-5.5, grok-4.7, gpt-5.6-sol
MediumOne protocol owner controls hook, factory, vault and LP lockerownershipAI
The same address, 0x263e…19Dd, owns the PonsV2MemeHook, PonsV2LaunchFactory, PonsV2BuybackVault and PonsV2LaunchLocker. The hook owner cannot renounce. On the hook, the owner can: - set the fee sweep operator; - call rescuePoolFees, which pays this pool's pending fees straight to the snapshotted protocol recipient and creator instead of through the escrow; - change global fee settings, which apply to future launches only. On the factory, the owner has rescueCurveFees and rescueSweptGraduation (the latter sends tokens/ETH out), forceSweptGraduation and per-launch overrides. The factory and locker source code was not provided, so the exact limits of these powers cannot be confirmed. Nothing seen lets this owner mint ZHOOK, block transfers or change this pool's fee rates. The main trust point is protocol-level fee handling and the unverified rescue paths. It is unknown whether this address is a multisig.
Evidence
- on-chainPonsV2MemeHook owner = 0x263ed295dAFaE1d9AAdD6E56c4B6F9f38eE019Dd; PonsV2LaunchFactory owner = 0x263ed295dAFaE1d9AAdD6E56c4B6F9f38eE019Dd; PonsV2BuybackVault owner = 0x263ed295dAFaE1d9AAdD6E56c4B6F9f38eE019Dd; PonsV2LaunchLocker owner = 0x263ed295dAFaE1d9AAdD6E56c4B6F9f38eE019Dd
- codePonsV2MemeHook.sol:L235-L237
Show source
function renounceOwnership() public pure override { revert OwnershipCannotBeRenounced(); } - codePonsV2MemeHook.sol:L555-L603
Show source
function rescuePoolFees(PoolId poolId) external onlyOwner nonReentrant returns (uint256 protocolAmount, uint256 creatorAmount) { LaunchInfo memory info = launches[poolId]; if (!info.registered) revert UnknownPool(); address quoteToken = info.quoteToken; if (quoteToken != address(0)) { (protocolAmount, creatorAmount) = _rescueCurrency(poolId, info, quoteToken); } (uint256 memecoinProtocol, uint256 memecoinCreator) = _rescueCurrency(poolId, info, info.memecoin); if (protocolAmount == 0 && creatorAmount == 0 && memecoinProtocol == 0 && memecoinCreator == 0) { - staticfactory fn rescueSweptGraduation(address,address) [owner] @PonsV2LaunchFactory.sol:L1254-L1286 — sends tokens out, sends ETH
Confirmed by: claude-opus-5.5, grok-4.7, gpt-5.6-sol
MediumBundled wallets bought a large share of supply at launchsnipersAI
Same-block bundles bought large shares of supply on the curve right after launch, for example 21.30% in block 98528044 and 12.01% in block 98528043. Wallet 0x9247…528b appears in five bundles. Two funding clusters were identified, and both hold 0% now. None of the bundle wallets appear among the current top 20 holders, which suggests this early supply has mostly been sold. Sniper checks are paused, so current bundle holdings are not fully measured.
Evidence
- on-chaintoken.bundles block 98528044 pctSupply=21.2984; block 98528043 pctSupply=12.0061; block 98528029 pctSupply=8.7675
- on-chaintoken.clusters pctSupplyHeldNow=0 (funders 0x53091256ebd2d8aa37b45536a5fd864ca764f32f, 0xf70da97812cb96acdf810712aa562db8dfa3dbef)
- on-chaintoken.notes
Show source
Sniper checks are paused in this version.
Confirmed by: claude-opus-5.5, grok-4.7, gpt-5.6-sol
MediumSite advertises private trading that docs and dApp test show isn't liveclaims-mismatchAI
The marketing site tells buyers every swap already runs through a shielded pool, a single-use stealth wallet, amount splitting, timing jitter and private RPC. The project's own docs mark the shielded balance Pending and say anything Pending or Roadmap is not shipped. A later team post lists stealth wallets, private swap and those anti-tracking tools as coming next, not live. Someone buying $ZHOOK for the privacy product may be paying for features the team has not shipped. This is a product-claim gap, not a token-contract power.
Evidence
Show source
Default mode Private Every swap runs through the shielded flow.Show source
A new wallet for every trade. Balances sit in a shielded pool. Each swap leaves from a single-use stealth walletShow source
Shielded balance PendingShow source
anything marked Pending or Roadmap is not shipped yet.Show source
Live: best-price swap, stock tokens, Swap API. Beta: shielded balance, private send, pay links. Next: private swap, stealth wallets, stealth orders, private payouts.Show source
Coming to Zerohook: the amount splitter.- forkdappTests: Swap ETH to USDG (passed=false)
Show source
wallet -0.01 ETH, +24.1965 USDG; 1 tx (execute ok) - forkdappTests: Swap USDG to ETH (passed=false)
Show source
No successful transaction was made for this goal (timeout). - forkdapp test: Swap ETH to USDG — transaction target and function
Show source
toRole=Uniswap Universal Router; function=execute(bytes,bytes[],uint256) - forkdapp test: Swap ETH to USDG — effects
Show source
wallet +24.1965 USDG ← 0x8876…0904 (Uniswap Universal Router) - forkdapp test: Swap ETH to USDG — observed
Show source
wallet -0.01 ETH, +24.1965 USDG; 1 tx (execute ok)
Confirmed by: grok-4.7, gpt-5.6-sol, claude-opus-5.5
LowOwner-picked operator sets slippage on fee conversion swapsfeesAI
Fees collected in ZHOOK are sold back into the pool, and buyback legs buy ZHOOK. Both happen in sweepPoolFees, which only the fee sweep operator may run when such a swap is needed. The owner sets this operator; it is currently 0xa101…cA83. The operator chooses the minimum-output limits. A careless or malicious operator could accept a poor price (for example in a sandwich), which would mostly cost fee recipients. Each internal swap's price movement is still capped by the pool's snapshotted maxInternalPriceImpactBps of 3%. These fee sells are a normal, ongoing source of selling pressure on ZHOOK.
Evidence
- codePonsV2MemeHook.sol:L500-L531
Show source
function sweepPoolFees(PoolId poolId, uint256 minConversionQuoteOut, uint256 minBuybackTokensOut) external nonReentrant { LaunchInfo memory info = launches[poolId]; if (!info.registered) revert UnknownPool(); bool isOperator = msg.sender == feeSweepOperator; if (!isOperator && msg.sender != info.creator) revert NotFeeSweepOperator(); if (!isOperator && _requiresTrustedOperator(poolId, info)) revert InternalSwapRequiresOperator(); (uint256 convertedFeeQuote, uint256 convertedTaxQuote, uint256 convertedBuybackQuote, bool converted) = _convertPendingMemecoin(poolId, info, minConversionQuoteOut); // Only a conversion that actually executed is subject to the caller's // minimum. Enforcing it when there was nothing to convert, or when the // swap filled nothing and the pending amount was restored for a later - codePonsV2MemeHook.sol:L274-L278
Show source
function setFeeSweepOperator(address operator) external onlyOwner { if (operator == address(0)) revert ZeroAddress(); feeSweepOperator = operator; emit FeeSweepOperatorUpdated(operator); } - codePonsV2MemeHook.sol:L766-L804
Show source
function _executeInternalSwap(PoolId poolId, SwapDirection direction, uint256 amountIn) private returns (uint256 amountInConsumed, uint256 amountOut) { bytes memory result = poolManager.unlock(abi.encode(poolId, direction, amountIn)); (amountInConsumed, amountOut) = abi.decode(result, (uint256, uint256)); } function unlockCallback(bytes calldata data) external returns (bytes memory) { if (msg.sender != address(poolManager)) revert NotPoolManager(); (PoolId poolId, SwapDirection direction, uint256 amountIn) = abi.decode(data, (PoolId, SwapDirection, uint256)); LaunchInfo memory info = launches[poolId]; PoolKey memory key = _poolKeys[poolId]; bool zeroForOne = - on-chainfeeSweepOperator = 0xa1018c1D9655292A2dE0F7dEa9a0F848EaA8cA83
Confirmed by: claude-opus-5.5, gpt-5.6-sol
LowTeam posts contradict each other on shielded balance statusclaims-mismatchAI
On 2 Nov the account said a zk-shielded ETH and USDG balance was live on mainnet. Docs still list Shielded balance as Pending, and the 4 Nov status post calls that same feature beta. Holders cannot tell from the team's own posts which privacy pieces actually work.
Evidence
Show source
zk-shielded balance in ETH + USDG (Groth16 proofs) ... Live on mainnet today. Private swap is next.Show source
Shielded balance PendingShow source
Deployment on Robinhood Chain is still being verified on-chain.
Confirmed by: grok-4.7, gpt-5.6-sol
LowWebsite domain registered one day before token launchwebsiteAI
The zerohook.trade domain was created on 2026-10-25, one day before the token was deployed on 2026-10-26. The Wayback Machine has no snapshots of it. This is a very new project with no track record.
Evidence
- on-chainsite.domainCreatedAt = 2026-10-25T06:18:55.000Z; contract.deployedAt = 2026-10-26T15:45:54.000Z; waybackSnapshots = []
Confirmed by: claude-opus-5.5, grok-4.7, gpt-5.6-sol
Positive signals (5)
PositiveOngoing token burns verified on-chain: 8.0% of supply burnedburnDeterministic
8.0% of the supply ever minted is burned, in 11 burn transfer(s), last 2026-11-04. Burned by: the deployer 0x80e7…7cdf (7.9%, 8 burns); holder 0x5d75…305e (0.02%, 3 burns). Burned tokens are gone for good, which reduces the supply over time.
Evidence
- on-chainTransfer events to 0x0 / 0x…dEaD and balanceOf(burn addresses) of 0x4a4fc33a4bf80d7bab0e1bab6d82af1e2942e917
Confirmed by: facts
PositiveFixed-supply token with no owner, mint, pause or blacklistotherAI
ZHOOK is the standard PonsV2LauncherToken: OpenZeppelin ERC20 plus a burn function holders can only use on their own tokens (or tokens they were approved to spend). The whole supply was minted once, to the bonding curve, in the constructor. There is no owner, no further mint, no blacklist, no pause and no transfer fee. The stored 'deployer' address is metadata only and gives no control. Slither found no issues.
Evidence
- codePonsV2LauncherToken.sol:L44-L71
Show source
constructor( string memory name_, string memory symbol_, string memory logo_, string memory description_, Socials memory socials_, address deployer_, address curve_, address launchFactory_, uint256 supply_ ) ERC20(name_, symbol_) { if (deployer_ == address(0) || curve_ == address(0) || launchFactory_ == address(0)) { revert ZeroAddress(); } - codePonsV2LauncherToken.sol:L7-L20
Show source
/** * @title PonsV2LauncherToken * @notice Fixed-supply ERC-20 deployed by PonsV2LaunchFactory for a v2 launch. * The entire supply mints directly to the token's bonding curve instead of a * Uniswap position. Anyone, the deployer included, may buy any amount from * the curve at any time; the curve's own price impact and its reserved pool * allocation are the only limits on a large buy. `deployer` is carried here * as immutable reference data for off-chain attribution only, and confers no * privileges over the token. * `ERC20Burnable` lets any holder voluntarily burn their own balance; the * protocol's buyback mechanism does not use it, bought-back tokens are * locked into `PonsV2BuybackVault` for a five-year vest instead of being * burned. */ - codeERC20Burnable.sol:L20-L38
Show source
function burn(uint256 value) public virtual { _burn(_msgSender(), value); } /** * @dev Destroys a `value` amount of tokens from `account`, deducting from * the caller's allowance. * * See {ERC20-_burn} and {ERC20-allowance}. * * Requirements: * * - the caller must have allowance for ``accounts``'s tokens of at least * `value`. */ - on-chaincontract.privileges = [] ; static.issues = []
Confirmed by: claude-opus-5.5, grok-4.7, gpt-5.6-sol
PositiveFork test: buys and sells work with 0% token taxhoneypotAI
A fork simulation bought and sold on the graduated Uniswap v4 pool. Both trades returned exactly the expected amounts. A second wallet that received tokens by transfer could also sell, and selling still worked one hour later. Token-level buy, sell and transfer tax were all 0%. No honeypot behaviour was seen.
Evidence
- forksimulation: canBuy=true, canSell=true, buyTaxPct=0, sellTaxPct=0, transferTaxPct=0
Show source
second wallet (received via transfer) could sell - forksimulation notes
Show source
sell after +1h: ok
Confirmed by: claude-opus-5.5, grok-4.7, gpt-5.6-sol
PositiveMain pool liquidity is 100% held by the Pons LP lockerliquidityAI
The main ZHOOK/ETH v4 pool (about $13.4k liquidity) is reported 100% locked, with 0% held by the deployer. The Pons locker also holds 8.16% of the token supply. The locker's function table shows only lock functions, callable by the factory, and no withdraw function. The locker source was omitted, so unlock terms cannot be fully confirmed.
Evidence
- on-chainliquidity pool 0x3bc3b16c1c4bce9379e9e5334c4d4a4d586ee8a85d655ff64e08912dedb51f30: lpLockedPct=100, lpHeldByDeployerPct=0
- staticLP-locker fns: lockPosition(address,uint256) [factory], lockTokenSupply(address,uint256) [factory], setFactory(address) [owner]
Confirmed by: claude-opus-5.5, grok-4.7, gpt-5.6-sol
PositiveDeployer holds no tokens and sold almost nothingholdersAI
The deployer wallet holds 0% now. It made 8 burns totalling 7.9478% of supply and sold only 0.0012%. The creator-declared insider wallet is the deployer itself, holding 0.0046%. Outside infrastructure, the largest holder has 2.93% and the top 10 hold 18.64%, a fairly spread distribution.
Evidence
- on-chaintoken.burns.by deployer 0x80e7a9cbbded990e481fb8bbcf971133bf217cdf pct=7.9478 count=8
- on-chainDeployer 0x80e7a9cbbded990e481fb8bbcf971133bf217cdf holds 0% now; deployerSoldPct=0.0012; top10Pct=18.6426
Confirmed by: claude-opus-5.5, grok-4.7 · Disputed by: gpt-5.6-sol
Notes (3)
LowPool takes a 3% fee per trade, frozen for this poolfeesAI
The graduated pool uses the PonsV2MemeHook. Its afterSwap callback takes the pool's hook fee plus a creator tax out of every swap; facts show 1% hook fee plus 2% creator tax. The simulation reports 0% because it counts this pool fee inside the quotes, not as a token tax. The fee rates are copied into the pool's record when the pool is registered, and afterSwap reads only that record. So the hook owner's setHookFeeBps cannot raise the fee on this pool. Registration also capped hook fee plus creator tax at 20%. The hook can only take an amount from swaps (afterSwapReturnDelta); it has no beforeSwap permission, so it cannot block buys or sells.
Evidence
- codePonsV2MemeHook.sol:L444-L485
Show source
function _afterSwap(address, PoolKey calldata key, SwapParams calldata params, BalanceDelta delta, bytes calldata) internal override returns (bytes4, int128) { // The conversion and buyback legs swap against this same pool, but // they are never taxed here: v4-core skips a pool's hooks when the // hook itself is the caller (Hooks.afterSwap). Were that not so, the // skim would come out of the buyback before it reached the vault. PoolId poolId = key.toId(); LaunchInfo memory info = launches[poolId]; if (!info.registered) return (IHooks.afterSwap.selector, 0); if (info.hookFeeBps == 0 && info.creatorTaxBps == 0) return (IHooks.afterSwap.selector, 0); bool specifiedIsCurrency0 = (params.amountSpecified < 0) == params.zeroForOne; - codePonsV2MemeHook.sol:L337-L378
Show source
// Terms frozen here govern the pool for life, so each is held to the // same ceiling as the setter that produced it. protocolFeeShareBps // against BASIS_POINTS rather than MAX_PROTOCOL_FEE_SHARE_BPS would // let a pool be registered on terms the live policy could never // reach, paying the creator nothing. if ( policy.protocolFeeRecipient == address(0) || policy.protocolFeeShareBps > MAX_PROTOCOL_FEE_SHARE_BPS || policy.buybackBurnBps > BASIS_POINTS || policy.hookFeeBps > MAX_HOOK_FEE_BPS || policy.maxInternalPriceImpactBps == 0 || policy.maxInternalPriceImpactBps >= BASIS_POINTS ) { revert InvalidBps(); } // The curve bounds the same sum in its own constructor rather than // inheriting it from the factory. A pool taking more than the whole // unspecified leg would flip the swapper's output delta negative. - codePonsV2MemeHook.sol:L184-L201
Show source
function getHookPermissions() public pure override returns (Hooks.Permissions memory) { return Hooks.Permissions({ beforeInitialize: true, afterInitialize: false, beforeAddLiquidity: false, afterAddLiquidity: false, beforeRemoveLiquidity: false, afterRemoveLiquidity: false, beforeSwap: false, afterSwap: true, beforeDonate: false, afterDonate: false, beforeSwapReturnDelta: false, afterSwapReturnDelta: true, afterAddLiquidityReturnDelta: false, - on-chainlaunchpad.fees
Show source
protocol fee 1%; creator tax 2%
Confirmed by: claude-opus-5.5, gpt-5.6-sol
InfoTeam openly discloses that no audit has been donewebsiteAI
Docs, the principles page and the token page all say no audit has been done and that they will not claim one until it is published. That is a disclosed gap in the trading app's contracts, not a hidden claim. It does not by itself show the $ZHOOK token can be drained.
Evidence
Show source
No audit has happened yet. Smart contract risk is real until audits are done and published.Show source
No audit yet No audit has happened yet. We will not say otherwise until one has.Show source
Is Zerohook audited? No audit has happened yet.
Confirmed by: grok-4.7, gpt-5.6-sol
InfoScanner bot flagged marketing running ahead of the appsocialAI
An automated scanner said private mode was marked soon in the app and that the site's private-by-default wording ran ahead of what it could test. It said it did not check the coin. Our comparison of the site, docs and the team's status post agrees with the wording gap. It is not independent proof of a rug.
Evidence
Show source
NARRATIVE: PARTLY REAL 35 · COIN: NOT CHECKED A real swap app exists, but private mode is marked 'soon' in the app itself. ... Site wording ahead of the product ... This checked the story only, NOT a coin.
Confirmed by: grok-4.7, gpt-5.6-sol
Score breakdown
Higher is safer. The overall is the weighted average of the assessed parts, then capped by hard facts.
Contract
weight 45%60Capped · max 60dApp asks for an unlimited token approval to an unreviewed spender → max 60
The token itself is a clean, fixed-supply template with working 0%-tax trades, but the dApp's unlimited approval request caps this score, and protocol-level owner powers remain.
Why this score
Raised the score
- Verified fixed-supply Pons template with no owner, mint, pause or blacklist
- Buy, sell, transfer-then-sell and delayed sell all pass at 0% token tax
- Pool fee rates frozen at 1% hook fee plus 2% creator tax
- Slither found no issues
Lowered the score
- dApp requests an unlimited USDG approval (Permit2)
- One protocol owner controls the hook, factory, buyback vault and LP locker
- Factory rescue functions and locker source were not reviewed
- Fee sweep operator sets slippage on fee swaps
Token
weight 30%50Liquidity is locked and the deployer holds nothing and burned about 8%, but same-block bundles captured a large share of supply right at launch.
Why this score
Raised the score
- Graduated pool liquidity 100% held by the Pons LP locker
- Deployer holds 0%, sold almost nothing and burned about 7.9%
- Ongoing burns verified on-chain
- Current holders fairly spread; top 10 hold about 18.6%
Lowered the score
- Bundles bought roughly 21%, 12% and 9% of supply in the first blocks
- One wallet appears in five launch bundles
- Sniper checks paused, so remaining bundle holdings are not fully measured
- Small pool liquidity of about $13.4k
Social / X
weight 15%45The X account is brand new and its posts are inconsistent about which privacy features are actually live, though there are no confirmed third-party scam calls.
Why this score
Raised the score
- No third-party rug or honeypot calls naming this token
- Team openly states no audit has happened
Lowered the score
- X account created on the same day as the token
- Posts disagree on whether the shielded balance is live or in beta
- Scanner bot noted marketing ahead of the product, which matches our facts
Website
weight 10%38The site presents private-by-default trading as current, but the dApp test showed a plain public swap and the project's own docs mark key privacy features as pending.
Why this score
Raised the score
- Working swap dApp, docs, terms and risk disclosure pages
- No-audit status disclosed in writing
Lowered the score
- Claim of stealth-wallet private trading contradicted by the dApp test
- Docs mark the shielded balance as pending while the site calls it the default
- Domain registered one day before launch with no archive history