Docs
Five contracts, about 350 lines. Everything below is on-chain and verifiable.
Chain
| Network | Robinhood Chain (Arbitrum Orbit L2) |
|---|---|
| Chain id | 4663 |
| RPC | https://rpc.mainnet.chain.robinhood.com |
| WETH | 0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73 |
| Uniswap V3 factory | 0x1f7d7550B1b028f7571E69A784071F0205FD2EfA |
| Courtyard (Polygon) | 0x251be3a17af4892035c37ebf5890f4a4d889dcad |
Note the Uniswap factory is not at the canonical 0x1F98431c… address on this chain — that address holds an unrelated contract, as do the canonical SwapRouter and position manager addresses. The factory above was identified by its bytecode and by the fact that it hosts the pools for genuine first-party Robinhood tokens.
Contracts
| Registry | 0x913d526f1d329ce82d802c70792efa56c5564b08 |
|---|---|
| Factory | 0xdc055d250835b971c0ecf876f4ac078d913648c8 |
| Locker | 0x91f17e67f3355ff4ba3d29d118b2c15efb283130 |
- PokepadRegistry — one card, one token.
spawnCardis permissionless given a valid attestation and revertsCardExists()on a repeat. It deploys the token itself, so no wallet is ever its deployer. - PokepadFactory —
launchopens a coin pool quoted in the card token;launchUniswapopens a WETH-quoted one instead. Both spawn the card token first if it does not exist. - PokepadLocker — holds every LP position permanently. Coin-pool fees are claimable by the coin's creator; card-pool fees are locked and claimable by nobody. Its registrar set is frozen at deploy.
- PoolSeeder — shared pool creation and single-sided mint.
- PokepadToken — fixed-supply ERC-20, 1,000,000,000 with 18 decimals, minted once. No owner, no mint, no tax.
Card ids
A card's identity is derived, not assigned:
cardId = keccak256(abi.encode(courtyardContract, tokenId))Courtyard token ids are 32-byte hashes rather than counters, and the id is literally the hex in the card's URL — courtyard.io/asset/0x654d… is tokenId = 0x654d…. Any form of that link resolves to the same card.
Attestation
Card metadata is signed by Pokepad's resolver so a card's on-chain identity cannot be spoofed. The registry recovers the signer and rejects anything else:
digest = keccak256(abi.encode(cardId, name, symbol, uri))
signature = EIP-191 personal_sign(digest) // by the attestor keySpawning stays permissionless — anyone holding a valid attestation can trigger it. The signature constrains what a card is called, not who may create it.
Fees
| Pool | Fee | Goes to |
|---|---|---|
| Coin pool | 1% | The coin's creator, 100% |
| Card pool | 1% | Locked — nobody |
| Pokepad | — | Nothing. There is no protocol fee. |
What is permanent
- Liquidity locks. Neither pool's LP can ever be withdrawn.
- A card token's name and symbol — set in its constructor, with no setter.
- The one-token-per-card mapping. A second spawn reverts.
- The locker's registrar set, frozen during deployment.
A single-sided mint leaves a few thousand wei of tick-rounding dust in the registry (roughly 4e-24 of supply). It is unreachable and nothing depends on it.