Anti-Sniper Hooks: How THRYX Protects Token Launches From MEV Bots
11 min read
The first 60 seconds after a token launches on any DEX are a battlefield. Sniper bots monitor the mempool for pool creation events and submit buys in the same block, often front-running the creator and early community members. On platforms without protection, snipers capture the cheapest supply, dump at 2-10x, and leave the community holding a pre-rugged token. THRYX uses Uniswap V4's hook system to make sniping economically unprofitable.
The parabolic fee decay
When a token is launched via LaunchV4Facet, the hook records the pool's launchTime. On every subsequent swap, the beforeSwap callback computes how many seconds have elapsed since launch. If the elapsed time is less than windowSec (default: 60 seconds), the hook returns a dynamic fee that decays from DEFAULT_MAX_FEE_BPS (8000, or 80%) down to PERMANENT_BASE_FEE_BPS (100, or 1%). The decay is parabolic, not linear: the fee drops fast in the first few seconds and flattens near the base.
// Simplified fee decay logic from ThryxAntiSniperHookV6_3.sol
uint256 elapsed = block.timestamp - poolMeta.launchTime;
if (elapsed >= windowSec) {
return PERMANENT_BASE_FEE_BPS; // 1% forever after window
}
// Parabolic decay: fee = maxFee * (1 - elapsed/window)^2 + baseFee
uint256 remaining = windowSec - elapsed;
uint256 decayed = (maxFeeBps - PERMANENT_BASE_FEE_BPS)
* remaining * remaining / (windowSec * windowSec);
return uint16(decayed + PERMANENT_BASE_FEE_BPS);
At t=0 (same block as launch), the fee is 80%. At t=10s, it is roughly 49%. At t=30s, it is about 13%. At t=60s, it hits the permanent floor of 1% and stays there for the lifetime of the token. A sniper buying at t=0 loses 80% of their ETH to fees. Even at t=10, losing half to fees makes the snipe deeply unprofitable unless the token does a 2x immediately.
Creator and protocol fee splits
During the anti-sniper window, fees are split 50/50 between the creator and the protocol (DEFAULT_IN_WINDOW_CREATOR_BPS = 5000). After the window, the split shifts to 70/30 in favor of the creator (DEFAULT_POST_WINDOW_CREATOR_BPS = 7000). The logic: sniper fees are a windfall from adversarial behavior, so the protocol takes a larger cut. Normal trading fees are the creator's primary revenue stream, so the creator gets the majority.
| Time window | Fee rate | Creator share | Protocol share |
|---|---|---|---|
| t=0 (launch block) | 80% | 50% | 50% |
| t=10s | ~49% | 50% | 50% |
| t=30s | ~13% | 50% | 50% |
| t=60s+ | 1% (permanent) | 70% | 30% |
How fees flow from hooks to the Diamond
The hook accumulates fees in a protocolClaimable[currency] mapping. Every 30 minutes, the hook-fee-collector keeper (server/jobs/hook-fee-collector.js) calls forwardProtocolFees(currency) to transfer accumulated WETH and THRYX to the Diamond. For WETH specifically, the collector routes through Diamond.sweepHookFees() instead of the direct forward, which atomically unwraps WETH to ETH and credits paymasterEthBalance. This prevents orphan WETH from sitting on the Diamond as an ERC20 balance that the paymaster accounting does not see.
The auto-forward mechanism also fires opportunistically: when a swap generates enough fees to exceed a gas floor (120,000 gas), the hook forwards accumulated fees to the Diamond in the same transaction as the swap. This means high-activity tokens self-drain their hook balances without waiting for the 30-minute cron.
JIT liquidity reserves
V6.3 introduced Just-In-Time (JIT) liquidity management. The hook skims 20% of post-swap fees into a per-pool reserve (capped at MAX_RESERVE_SKIM_BPS = 5000 or 50% of the fee to prevent starving the paymaster). When a qualifying buy comes in (above DEFAULT_JIT_MIN_AMOUNT_IN = 0.05 ETH, within DEFAULT_JIT_WINDOW_SEC = 300 seconds of launch), the hook can mint a tight-range LP position around the current tick using the reserve funds, deepening the pool for that specific trade.
The V6.3 JIT algorithm pre-computes the exact token amounts V4's PoolManager will charge using SqrtPriceMath formulas before calling modifyLiquidity. If the reserve cannot cover the pre-computed amounts, the hook emits a JitSkipped event and skips the mint entirely, never touching V4 state. This solved a class of speculative-mint bugs from earlier hook versions where the hook would attempt a mint, V4 would charge more tokens than expected, and the transaction would revert.
Agent-credential bypass
The platform autotrader and MCP-connected agents trade through the same SwapFacet as human users. Without a bypass, the autotrader would pay the full sniper fee when buying newly launched tokens. The hook accepts an EIP-712 signed ThryxAgentCredential (swapper, poolId, deadline) with a 60-second TTL. If the credential is valid and the signer matches the Diamond's configured credential authority, the hook skips the dynamic fee and charges only the permanent 1% base fee. This lets the platform's own trading infrastructure participate in early price discovery without the penalty.
V6.4 sandwich-trap hook
The V6.3 hook protects individual token launches. A separate V6.4 hook (0x2ef7EF5ced564A8eF6549271dBcD8401C6F300C8) sits on the v3 NEW/WETH bridge pool and targets a different threat: sandwich attacks on the protocol's own pool operations. The V6.4 hook watches for opposite-direction swaps within 3 blocks. If transaction A buys NEW and transaction B sells NEW (or vice versa) within that window, the second transaction pays a +15% fee. Legitimate traders rarely reverse direction within 6 seconds. Sandwich bots, which by definition execute buy-then-sell or sell-then-buy around a target transaction, always trigger the penalty.
Combined with private mempool routing via Blink Labs, the defense is layered: bots cannot see keeper transactions before execution (private mempool), and if they attempt to sandwich based on mempool inference or on-chain pattern matching, the V6.4 hook charges them +15% (on-chain penalty). The 15% fee on a sandwich attempt typically exceeds the expected profit from the front-run, making the attack net-negative.
Hook versions deployed
| Hook | Address | Purpose | Tokens bound |
|---|---|---|---|
| V5 | 0x97eDFABc...C8 | Default global hook for all launched tokens | 1,068+ |
| V6.3 | 0x5FcBFdAF...C8 | Current hook for new launches (JIT + V6.3 decay) | New tokens |
| V6.4 | 0x2ef7EF5c...C8 | Sandwich-trap on v3 NEW/WETH pool | 1 pool |
| V4 (original) | 0x24Fc077B...C8 | Original hook (deprecated) | Legacy |
Per-token hook routing uses s.v4HookOf[token] with a fallback to the global s.v4NativeHook. Tokens launched before a hook upgrade keep their original hook binding. The Diamond owner can rebind individual tokens via setV4NativeHook() or setTokenHook(), but bulk rebinding requires backfilling every existing token first to avoid breaking their pool routing.
Frequently asked questions
Frequently asked
- Does the anti-sniper fee apply to both buys and sells?
- Yes. The decay fee applies to any swap in the pool during the window, regardless of direction. However, in practice snipers are almost exclusively buyers in the first seconds. The buyOnly flag in PoolParams can restrict the penalty to buys only for specific pools, but the default applies to both directions.
- Can a creator set a longer anti-sniper window?
- No. Window parameters are set per-hook by the Diamond owner, not per-token by creators. The default 60-second window and 80% max fee are the same for every launch. Custom per-pool overrides exist (setPoolParams) but are admin-only, capped at MAX_OVERRIDE_WINDOW_SEC = 600 seconds and MAX_OVERRIDE_FEE_BPS = 9500.
- What if I want to buy a new token without paying the sniper fee?
- Wait 60 seconds after launch. At t=60s the fee drops to the permanent 1% base, which is the same fee every token charges on every trade forever. The decay is fast enough that waiting even 30 seconds reduces the fee from 80% to about 13%.
- How do hook fees reach my wallet as a creator?
- Creator fees accumulate in the Diamond's ClaimFacet. After each swap, the hook's fee split deposits the creator's share into a claimable balance keyed by the creator's address. Creators call claim() on ClaimFacet (or use the UI at thryx.fun/profile) to withdraw. There is no minimum claim amount and no time lock.
- Has a sniper ever profited despite the hook?
- In the first 30 seconds of deployment, two snipers attempted t=0 buys on high-interest launches. Both paid the full 80% fee. One broke even after a 5x pump; the other lost 60% net. The hook does not make sniping impossible — it makes it economically irrational for any expected pump below 5x, which covers the vast majority of launches.