Build with Signal
Discover v4 pools
A token is a Signal v4 launch when a reviewed Signal factory bore it. A ticker, a picture, an API search hit or a pool that merely contains the token proves nothing.
The birth events
Every launch emits one Launched from its factory. Release 4.2 also emits Details in the same transaction.
event Launched(
bytes32 indexed id, // the Uniswap v4 pool id
address indexed token,
address indexed creator, // the launching wallet
address quote, // the pair asset
bool rewards, // true: a holders token
uint16 poolFeeBps,
uint16 buyTaxBps,
uint16 sellTaxBps,
uint16 protocolBps,
Split split, // (creator, holders, liquidity, burn, floor), bps
uint256 firstBuyTokens, // tokens the launcher's first buy received, 0 if none
Blocks blocks, // the launch's optional rules
Leg[] legs, // named co-recipients of the creator side
Module module,
uint128 liqBatchQuote
);
event Details(address indexed token, bytes32 metaHash, string uri);| Event | Topic 0 |
|---|---|
Launched (4.2 and 4.1) | 0x8fd460cf6081c16be4921e6d01164cb0745944b824325879617eefd6a81b3f7b |
Details (4.2) | 0x4b87591452f11d5711de01c570b9a9519aa41e8dccd0e5878dc6c53c4eeb4514 |
Launched (release 2) | 0x8a27775651889aee0c899890c76e303ec5efd6b0a63392cecd6a040572142e56 |
Release 2's Launched is the same event without the last two fields (module, liqBatchQuote), so its topic differs.
Decode with the factory ABI; the struct layouts are in it. Scan only the factory addresses in the deployment record, from each one's first block. Use bounded block ranges, keep a cursor and backfill what you miss. Some public HyperEVM RPC endpoints return an empty result, not an error, for a log range they consider too wide: page in small ranges and confirm a known launch appears before trusting an empty answer.
The event is a trigger. The authority is the hook's own record, read back at a pinned block.
Another route: the PoolManager
Every pool is created through the PoolManager, so its Initialize log names the pool's hook. Filtering Initialize by hooks in Signal's hook list finds the same pools without a factory ABI. A new Signal hook means a new address to add to that list.
Confirm the identity at one block
factory.poolOf(token)returns a non-zero pool id, andfactory.isSignalToken(token)is true.hook.terms(id).tokenis the token, andhook.terms(id).quoteis the pair asset you expect.hook.poolKey(id)returnsfee = 0,tickSpacing = 200,hooks= that hook, and the two currencies are the token and the pair asset in address order.keccak256(abi.encode(currency0, currency1, fee, tickSpacing, hooks))equals the pool id.factory.hook()is the hook andhook.factory()is the factory.- On release 4.2, the token's code is the EIP-1167 minimal clone of the plain implementation, or of the holders implementation when
terms.rewardsis true.
The read-only example performs these checks.
Token facts
| Fact | Where to read it |
|---|---|
| Supply and decimals | totalSupply() is 1,000,000,000 × 10^18; decimals() is 18 |
| Holders token or plain | rewardsEnabled(), or terms.rewards |
| Pair asset | terms.quote; a holders token also exposes rewardAsset() |
| Launcher | Launched.creator, and hook.creatorOf(id) |
| Launch time | terms.launchTs (unix seconds) |
| Start price | terms.startTp, a tick: price in pair-asset units per token = 1.0001^startTp, before decimals |
Names can change
A release 4.1 or 4.2 token is a plain ERC-20 with one unusual power: its launcher (identityOwner()) can change the token's name and symbol with setIdentity, at most once every 24 hours. The token emits IdentitySet(string name, string symbol), and bornName() and bornSymbol() keep what it was launched as. The address, the pool and every rule stay the same. Release 2 tokens do not have this: their name and symbol are fixed and these calls revert.
Index a token by address. Refresh the name and ticker on IdentitySet. Treat a ticker match as nothing more than a ticker match.
Words and pictures
contractURI() on a 4.2 token returns https://signal.family/api/meta/0x<token>, an ERC-7572 document: name, symbol, description, image, website, external_link, twitter, telegram. The token stores none of it. The factory's Details event carries the uri the launcher supplied (on current launches a https://signal.family/m/<hash> address) and metaHash = keccak256(bytes(uri)), the hash of that address string. It records which address the token was launched with. It does not commit to the document's contents, which Signal's server supplies.
All of it is display content supplied by a launcher. Never let it choose a spender, an RPC host, a route or a transaction recipient.
API-assisted discovery
| Read | Use |
|---|---|
/api/born?every=1 | Every launch, newest first, in pages. A v4 row has launch_venue: "v4" and pad_addr = its factory |
/api/token/<address> | The token record with v4_launch: pool id, pool key, terms as read at the birth block, and cached hook state |
/api/config | Which factory is open, and the admitted pair assets |
These are indexed views with their own freshness. See the public data API. Rebuild durable history from chain logs when your product needs completeness.