Blog

Two blocks: what the launch window actually protects

Per-wallet caps cannot stop a sniper with a hundred wallets. Block numbers can. A walk through the token’s transfer hook, the launch-block lockout, and the one exemption.

August 22, 2026 6 min readsecuritycontracts

Anti-snipe mechanisms usually cap how much one wallet can buy. A sniper answers with more wallets. The cost of a hundred addresses is a hundred gas fees, which against a good launch is nothing. Any protection that reasons about wallets is therefore decoration unless it also reasons about time.

The token’s _update hook reasons about block.number. Here is what it does, in order of the blocks it applies to.

The launch block: nobody buys

If a transfer comes from the pool in the block the token was created, it reverts LaunchBlockBuyBlocked — unless it is the single recipient the factory registered for its own atomic opening buy, and only while that registration is open. The factory opens it, executes the buy, and closes it, all inside launchToken. A sniper who lands a transaction in the same block as the launch, whether by mempool watching or by luck, gets a revert. Not a small fill, not a taxed fill: a revert.

Blocks +1 and +2: everyone is capped

For the next two blocks a pool-to-wallet transfer must leave the recipient at or below maxWalletLimit() — 5% of supply — and must keep their cumulative pool buys at or below maxTxLimit() — 5.5%. The cumulative counter is per recipient, so splitting one buy into several in the same block does not help. The 10% headroom between the two limits exists so a wallet near the cap can still complete a buy whose rounding would otherwise fail; the factory enforces maxTxBps == 110% of maxWalletBps when a config is added.

Block +3: nothing

restrictionEndBlock = launchBlock + 2, and the hook checks block.number ≤ restrictionEndBlock. After that the token is an OpenZeppelin ERC-20 with no extra behaviour. There is no permanent tax, no permanent cap, no owner who can turn one back on.

Only buys, and only from a real pool

The rules apply when from is a pool. Sells into the pool, wallet-to-wallet transfers and contract interactions are untouched. And “a pool” is checked properly: the hook matches the canonical pool and also asks the Uniswap factory whether from is the pool for (this token, WETH) at whatever fee tier from reports. Creating a second pool at a different tier to route around the hook does not work.

What this does not do

It does not stop a well-funded actor from using twenty wallets in block +1 to accumulate. Nothing keyed to wallets can. What it guarantees is narrower and more useful: the first fill anyone other than the creator can get is at least one block after the creator’s, no single address can hold more than 5% via the pool in that window, and the creator’s own buy is public in the launch event before anyone else can act. On Robinhood Chain, which produces something like ten blocks a second, the whole window is a fraction of a second. It is about ordering, not duration.