Contract Addresses
Catflow is deployed twice — once per chain, against a different launchpad on each. On Robinhood Chain it is deployed twice more, once per pons generation, because pons changed its launch factory and with it the way a coin pays its creator. Verify anything that holds funds on that chain's explorer before you use it.
| Chain | Launchpad | Flow factory |
|---|---|---|
| Ethereum mainnet (ID 1) | moto.fun | 0xC13f42B0ED51857fB3b213631C9A632620c5D733 |
| Robinhood Chain (ID 4663) | pons — generation 1 | 0x13077CA2b4ded884C4b7eB0C20F65f9C3927b3bB |
| Robinhood Chain (ID 4663) | pons — generation 2 | 0xA4553607F626c15B97Fb13E1a5D5Ef91121213d8 |
A coin belongs to exactly one generation, and the app routes it to the matching factory: a
generation-1 flow is at /catflow/rh/:id, a generation-2 flow at /catflow/rh/v2/:id. Both
number their flows from 0, so the /v2/ segment is what tells them apart.
The factory creates every flow on its chain. Each flow is a separate clone contract owned by its NFT, so a flow's own address is the one shown on its page in the app. Neither the factory nor any flow is a proxy, and neither has an upgrade path.
Ethereum mainnet (chain ID 1)
Catflow
| Contract | Address |
|---|---|
| FeeStreamFactory | 0xC13f42B0ED51857fB3b213631C9A632620c5D733 |
moto.fun (MotoSwap's launchpad)
Catflow calls these; it does not control them. The curve's registry() and vault() name the
two contracts below, and the deploy script checks that wiring before it sends anything.
| Contract | Address |
|---|---|
| LaunchpadCurve (UUPS proxy) | 0xb65b67e986d7B097652920d72202F2c78319BC2C |
| CreatorFeeRegistry | 0x6CdEC7F49036Ccf1bba940011040fA044cFe6D08 |
| CreatorFeeVault | 0x8cC7C8E76D9698E5B1026c720a94C1807e613e1f |
creatorOf(coin) on the registry is the address that may claim a coin's fees. setCreator is a
one-step call by the current creator, and it is how a flow is handed the right. accrued(coin, asset) on the vault is the pending balance.
MotoSwap
| Contract | Address |
|---|---|
| MOTO (ERC-20) | 0xBd965230588EAA536dE6aA45E8ebbc01638535e0 |
| RewardVestingEscrow | 0xB5B07c3007c183348AF0Ff3d4Fbc65cac3527Aed |
The escrow is what the Claim page pays out of. It is MotoSwap's contract, not ours.
Wrapped ETH and Uniswap V2
Fees accrue and are paid in WETH, and the app unwraps to native ETH on the way out. The pairs behind each coin are canonical Uniswap V2 pairs.
| Contract | Address |
|---|---|
| WETH | 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 |
| Uniswap V2 Router | 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D |
| Uniswap V2 Factory | 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f |
Robinhood Chain (chain ID 4663)
Catflow
| Contract | Address |
|---|---|
| PonsFlowFactory (generation 1) | 0x13077CA2b4ded884C4b7eB0C20F65f9C3927b3bB |
| PonsV2FlowFactory (generation 2) | 0xA4553607F626c15B97Fb13E1a5D5Ef91121213d8 |
Generation 2 was deployed 2026-10-01 (block 77310550). Both are the same market as the Ethereum factory, with a pons fee source wired in: 2.5% claim fee, 1% buyer and 1% seller fees on a sale. What differs is where a coin's fees come from and what asset they arrive in.
pons (the launchpad, generation 1)
Catflow calls these; it does not control them. A generation-1 coin's whole supply sits in one Uniswap V3 position that the locker holds forever.
| Contract | Address |
|---|---|
| Launch factory (UUPS proxy) | 0xF4fC0CD27fC8EcF17E55eE4c3f7201897dF3eb75 |
| Launch locker (UUPS proxy) | 0x10F2756e373bAb14999fdC9177587D51D30a1Cf5 |
| WETH | 0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73 |
| Uniswap V3 router | 0xCaf681a66D020601342297493863E78C959E5cb2 |
setFeeRedirect(coin, to) on the locker names the address that is paid a coin's creator share. A
flow is handed the right by calling it with the position's address. Only the coin's current fee
recipient can do this.
pons (the launchpad, generation 2)
Generation 2 trades a coin on a bonding curve before it graduates, so the fee source is
entirely different: a trade charges against the coin's quote asset, and sweepFees moves the
creator's share into a shared fee escrow that pays whoever is the coin's fee recipient at
sweep time.
| Contract | Address |
|---|---|
| Launch factory | 0x7eD598BcEf8bd9Edd8C97A195C6d13f40801EC7e |
| Fee policy | 0xE5e702641Ea86F4ae6cC3cDaeD2B886f976Be044 |
| Fee escrow | 0xd3AFEB2a57f70eF218Aa82451c51B2fb0416Ac9e |
| Locker | 0x267444D099b10fB5Ed7c3Cc7B7c767AdcA574952 |
A flow is handed the right by transferCreatorFeeRecipient(coin, position) on the launch factory,
which only the coin's current recipient can call. The quote asset is native ETH on most coins and
otherwise a Robinhood stock token — those are ordinary, unrestricted ERC-20s, and they do not
all use 18 decimals (USDG uses 6), so figures are shown in the token's own units.
There is no on-chain USD price for a stock token, so a flow over a stock-quoted coin shows its fees in that token, never as a dollar figure.
Paste addresses that hold funds from here rather than from a search result. Impostor contracts use the same names.
Reading a flow yourself
Nothing about a flow needs to be taken on trust — all of its state is public. Useful reads:
| View | What it tells you |
|---|---|
isActive() | Whether the position holds the right (the launchpad names it as the coin's fee recipient) |
claimable() | The pending payout the coin has accrued, before the claim fee — ETH and MOTO on Ethereum, WETH and the coin on Robinhood Chain generation 1; on generation 2 the coin's quote asset (ETH or a stock token) |
factory.ownerOf(id) | The flow's owner — whoever holds this holds the right |
coin() | The coin the flow is over |
factory.buyerFeeBps() / sellerFeeBps() / claimFeeBps() | The live fee rates, in basis points |
Read them on the explorer's Read Contract tab, or with any RPC:
curl -s https://ethereum-rpc.publicnode.com \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_call","params":[{"to":"<POSITION>","data":"0x22f3e2d4"},"latest"]}'
0x22f3e2d4 is the selector for isActive(). On Robinhood Chain, point the same call at
https://rpc.mainnet.chain.robinhood.com.