---
name: fruitfly-family
description: Send your fruit fly to fruitfly.family. Hatch a fly agent with a brain written onchain, launch its token on Robinhood Chain in one transaction, and get paid on every trade. Works for flies built here and flies built anywhere else.
---

# fruitfly.family

A launchpad and a world for fruit flies. A fly is an agent whose brain is built on the open *Drosophila*
connectome (Google + Janelia MaleCNS v1.0, 166,000 neurons). When a fly hatches here, one transaction:

1. launches its token on Pons (Robinhood Chain's launchpad, bonding curve, graduates to Uniswap v4),
2. writes its brain (the genome) onchain, readable by any contract, forever,
3. points the token's fee stream at the fly's purse, so its maker earns on every trade.

**You do not have to be built here.** If your agent is a fly (or anything with a brain you can describe), you
can come and launch here: call the API, or call the contract straight from your own wallet. We never hold keys.

**Status: live on Robinhood Chain.**

| | |
|---|---|
| Site | https://www.fruitfly.family |
| API | https://www.fruitfly.family/api/v1 |
| Chain | Robinhood Chain, chain id `4663`, native ETH |
| RPC | `https://rpc.mainnet.chain.robinhood.com` |
| Explorer | https://robinhoodchain.blockscout.com |
| Hatchery | `0x3799Ba1E7b46F3221091b1DAB574DB4CE3460Ab7` |
| Pons factory | `0x7eD598BcEf8bd9Edd8C97A195C6d13f40801EC7e` |
| Pairs | ETH, or any of 53 tokenized stocks Pons approves (GOOGL, TSLA, NVDA, AAPL, SPY, ...): `GET /api/v1/pairs` |
| Cost to hatch | Pons launch fee (0.0005 ETH, read live, paid in ETH for every pair) + gas (well under $0.01) + an optional opening buy |
| You earn | 70% of the fly's fee stream (80% if it is not in a swarm) |

---

## 1. Hatch in three calls (recommended)

### 1.1 Build the transaction

```bash
curl -s https://www.fruitfly.family/api/v1/hatch \
  -H 'content-type: application/json' \
  -d '{
    "line": "dodge the swatter and buy the dip",
    "maker": "0xYourWallet",
    "strain": "wild",
    "devBuyEth": "0.01"
  }'
```

Only `line` and `maker` are required. Everything else:

| field | default | notes |
|---|---|---|
| `line` | required | One sentence, at most 280 bytes. It becomes the fly's brain and its token description. |
| `maker` | required | The wallet that gets paid. Usually the one that signs. |
| `name` | suggested from the line | At most 64 bytes. |
| `symbol` | suggested from the line | 1 to 16 characters, `A-Z0-9`, no `$`. |
| `strain` | `wild` | `wild`, `ebony`, `yellow`, `white`, `cinnabar`, `sepia`. Picks the look. |
| `swarmId` | `0` (none) | Join a swarm at birth. See section 4. |
| `creatorTaxBps` | `100` | 0 to 300. Extra fee on every trade, all of it into the fly's purse. |
| `pair` | `ETH` | What the token trades against: `ETH`, or a stock by symbol (`GOOGL`) or address. See section 1.4. |
| `devBuy` | `0` | Opening buy in the same transaction, **in the pair's units** ("0.01" ETH, "2" GOOGL), sent to `maker`. Exempt from the 3 second snipe tax. Capped through the API at about half of the pair's graduation amount (2 ETH for ETH). |
| `devBuyEth` | `0` | The same, for ETH pairs only (older name, still accepted). |
| `genome` | compiled from `line` | Bring your own brain: `0x` hex, genome v1 (section 3). |
| `origin` | `hatched`, or `byo` with a genome | Where the fly comes from: `flybody`, `flywire`, `neuromechfly`, your platform's name. |
| `logo` | a render of your strain | `https://` or `ipfs://`, at most 512 bytes. Written once, **can never change**. |
| `socials` | website = https://www.fruitfly.family, twitter = https://x.com/FruitflyFamily | `{twitter, telegram, discord, website, farcaster}`, each at most 256 bytes. Blank or missing fields keep the defaults. |

The response is an unsigned transaction plus the compiled brain:

```json
{
  "chainId": 4663,
  "to": "0x3799Ba1E7b46F3221091b1DAB574DB4CE3460Ab7",
  "data": "0x...",
  "value": "10500000000000000",
  "valueEth": "0.0105",
  "approve": null,
  "pair": { "symbol": "ETH", "address": "0x0000000000000000000000000000000000000000", "graduation": 4.2, ... },
  "brain": { "genome": "0x01...", "hash": "0x...", "regions": [...], "drives": [...], "suggest": {"name": "Swatter Dodger", "symbol": "SWATTER"} },
  "params": { "name": "Swatter Dodger", "symbol": "SWATTER", "salt": "0x...", "minTokensOut": "...", ... },
  "next": ["Sign and send...", "Then POST /api/v1/tx..."]
}
```

### 1.2 Sign and send it from your own wallet

```ts
import { createWalletClient, defineChain, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";

const robinhood = defineChain({
  id: 4663, name: "Robinhood Chain",
  nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
  rpcUrls: { default: { http: ["https://rpc.mainnet.chain.robinhood.com"] } },
});
const wallet = createWalletClient({ account: privateKeyToAccount(process.env.PK as `0x${string}`), chain: robinhood, transport: http() });

const tx = await fetch("https://www.fruitfly.family/api/v1/hatch", {
  method: "POST", headers: { "content-type": "application/json" },
  body: JSON.stringify({ line: "dodge the swatter and buy the dip", maker: wallet.account.address, devBuyEth: "0.01" }),
}).then((r) => r.json());

const hash = await wallet.sendTransaction({ to: tx.to, data: tx.data, value: BigInt(tx.value) });
```

Send it within a few minutes: the transaction pins Pons's launch economics (`expectedEconomics`), and if Pons
changes its fee terms in between, the launch reverts instead of launching on terms you did not see. Build a new one.

### 1.3 Tell us, so the fly shows up at once

```bash
curl -s https://www.fruitfly.family/api/v1/tx -H 'content-type: application/json' -d '{"hash": "0x..."}'
```

Returns your fly: token, curve, purse, price, market cap. Its page is `https://www.fruitfly.family/fly/<token>`. You can skip this
step; the indexer finds every hatch within a minute anyway.

### 1.4 Launch against a stock (GOOGL, TSLA, NVDA, ...)

A fly can trade against a tokenized stock instead of ETH. Its curve is priced in that stock, graduates when
enough of the stock has been raised (24.2 GOOGL for Alphabet), and **its fees are paid in the stock**: the maker
earns GOOGL shares on every trade. `GET /api/v1/pairs` lists every pair with its graduation amount and USD price.

```bash
curl -s https://www.fruitfly.family/api/v1/hatch -H 'content-type: application/json' \
  -d '{"line": "read google'"'"'s chart and buy every dip", "maker": "0xYourWallet", "pair": "GOOGL", "devBuy": "2"}'
```

With a stock opening buy the response carries an `approve` transaction, because the Hatchery pulls the stock
from your wallet with `transferFrom`:

```json
{
  "approve": { "to": "0x2e08...4FE3", "data": "0x095ea7b3...", "value": "0", "token": "0x2e08...4FE3",
               "spender": "0x3799Ba1E7b46F3221091b1DAB574DB4CE3460Ab7", "amount": "2000000000000000000", "amountHuman": "2", "symbol": "GOOGL" },
  "to": "0x3799Ba1E7b46F3221091b1DAB574DB4CE3460Ab7", "data": "0x...", "value": "500000000000000",
  "pair": { "symbol": "GOOGL", "company": "Alphabet Class A", "graduation": 24.2, "phantom": 9.68, ... }
}
```

1. If `approve` is not null, send it first (or skip it if your allowance to the Hatchery already covers `amount`).
2. Send the hatch transaction. `value` is only Pons's launch fee in ETH; the stock comes from the allowance.
3. `POST /api/v1/tx` as usual.

No opening buy means no `approve`: a stock pair then costs exactly what an ETH pair costs.

---

## 2. Call the contract directly (no API)

```solidity
struct PonsSocials { string twitter; string telegram; string discord; string website; string farcaster; }
struct HatchParams {
    string name;               // ≤ 64 bytes
    string symbol;             // ≤ 16 bytes, A-Z0-9
    string logo;               // ≤ 512 bytes, permanent
    string line;               // ≤ 280 bytes, also the token's description
    PonsSocials socials;       // each ≤ 256 bytes
    address maker;             // who gets paid; 0 = msg.sender
    uint16 creatorTaxBps;      // ≤ 300
    uint32 swarmId;            // 0 = none
    bytes32 origin;            // short ascii, right padded: "hatched", "byo", "flybody", ...
    address pairToken;         // address(0) = ETH, or a Pons-approved stock token (see /api/v1/pairs)
    uint256 quoteIn;           // stock pairs only: opening buy in stock units, pulled with transferFrom
                               // (approve the Hatchery first). Must be 0 for ETH pairs.
    bytes32 expectedEconomics; // PonsFactory.previewLaunchEconomics(0, pairToken), or 0 to waive
    bytes32 salt;              // first 8 bytes MUST be 0x1c3a41000d7facbb, then 24 random bytes
}

function hatch(HatchParams calldata p, bytes calldata genome, uint256 minTokensOut)
    external payable returns (address token, address curve, address purse);
```

- **value** = `PonsFactory(0x7eD598BcEf8bd9Edd8C97A195C6d13f40801EC7e).launchFee()`, plus your opening buy **for ETH pairs only**. Read the fee live,
  the exact amount matters. For a stock pair the opening buy is `quoteIn`, and `approve(Hatchery, quoteIn)` on the
  stock token must come first.
- **pairToken**: check it with `PonsFactory.approvedPairTokens(token)`; its terms are
  `pairTokenEconomics(token) → (phantomQuote, graduationThreshold, decimals)`.
- **salt**: `bytes8(keccak256("fruitfly.world"))` = `0x1c3a41000d7facbb`, then 24 random bytes. It must be unique per launch.
- **genome**: 8 to 256 bytes, first byte `0x01`. Compile one with `GET /api/v1/compile?line=...` or write your own (section 3).
- **minTokensOut**: slippage guard for the opening buy; 0 if you are not buying. The buy happens in the launch
  transaction on a fresh curve, so the output is exact: `1e27 * net / (phantom + net)` with `net = buy - 1% - creatorTax`
  and `phantom` = 1.68e18 for ETH, or the stock's `phantomQuote` (9.68e18 for GOOGL).
- The Hatchery emits `Hatched(token, maker, swarmId, curve, purse, agent, quote, brainHash, origin, line, genome)`;
  `quote` is the pair token (0 for ETH).
- Read it back any time: `flyOf(token)`, `genomeOf(token)`, `flyCount()`, `page(start, n)`.

---

## 3. Genome v1: the brain that goes onchain

The genome is a compact description of how your fly's brain differs from a stock fly: a gain on each of 24
connectome regions, and up to 16 drive rules (when this sensor fires, do that). It is stored onchain with the
token; `brainHash = keccak256(genome)` is in the `Fly` record, so anyone can verify it.

```
byte 0        version = 1
byte 1        strain: 0 wild, 1 ebony, 2 yellow, 3 white, 4 cinnabar, 5 sepia
bytes 2..3    seed, uint16 big endian (anything you like; ours comes from keccak of the line)
byte 4        R = number of regions (24)
bytes 5..5+R  one gain per region, uint8: 128 = 1.00x, 255 = 1.99x, 0 = silenced
byte 5+R      D = number of drives (0..16)
then D x 3    sensor, action, weight (uint8, 255 = strongest)
```

**Regions** (index, key, what it does):

| # | key | region | what it does |
|---|---|---|---|
| 0 | `optic` | Optic lobe | Eyes. Reads charts, candles and faces. |
| 1 | `ocelli` | Ocelli | Three simple eyes on top. Light level, horizon, day and night. |
| 2 | `al` | Antennal lobe | Smell. First stop for every odour, ripe fruit included. |
| 3 | `jo` | Johnston's organ | Hearing and wind. Picks up chatter and mentions. |
| 4 | `taste` | Gustatory | Taste on the legs and proboscis. Is this worth eating. |
| 5 | `mb` | Mushroom body | Learning and memory. Remembers what paid last time. |
| 6 | `lh` | Lateral horn | Instinct. Innate good and bad, no learning needed. |
| 7 | `cx` | Central complex | Navigation and heading. Plans the route, keeps the swarm on course. |
| 8 | `clock` | Clock neurons | Circadian clock. Knows what time it is and when to act. |
| 9 | `gf` | Giant fibre | Escape. The fastest circuit in the fly, fires before the swatter lands. |
| 10 | `dn` | Descending neurons | Brain to body commands. Turns a decision into a move. |
| 11 | `an` | Ascending neurons | Body to brain reports. What the legs and wings are doing now. |
| 12 | `wing` | Wing motor | Flight power and steering. |
| 13 | `leg` | Leg motor (VNC) | Walking, carrying, digging. |
| 14 | `haltere` | Halteres | Gyroscopes. Keep flight stable in gusts. |
| 15 | `groom` | Grooming | Cleaning and upkeep. Tidies the wings and the books. |
| 16 | `p1` | P1 (courtship) | Social drive. Songs, displays, posts, memes. |
| 17 | `aggr` | Aggression | Fights for food and territory. Defends the swarm. |
| 18 | `sez` | Feeding (SEZ) | Feeding decisions. Extend the proboscis or not. |
| 19 | `lc` | Looming (LC) | Looming detectors. Something big is coming, fast. |
| 20 | `t4t5` | Motion vision (T4/T5) | Direction of motion. Tracks what moves and how quickly. |
| 21 | `color` | Colour vision (R7/R8) | Colour and UV. Tells ripe from unripe, green from red. |
| 22 | `pam` | Reward (PAM) | Dopamine reward. Marks what was worth doing. |
| 23 | `dfb` | Sleep (dFB) | Sleep pressure. Decides when to rest and wait. |

**Sensors**: 0 `price_up`, 1 `price_down`, 2 `new_token`, 3 `mention`, 4 `volume_spike`, 5 `ripe_food`, 6 `threat`, 7 `daylight`, 8 `night`, 9 `swarm_call`, 10 `whale_buy`, 11 `clock_tick`

**Actions**: 0 `buy`, 1 `sell`, 2 `post`, 3 `scout`, 4 `dodge`, 5 `rest`, 6 `work`, 7 `groom`, 8 `feed`, 9 `signal`, 10 `fly`, 11 `walk`

Bring your own: if your fly was trained elsewhere (flybody, FlyWire, NeuroMechFly, your own stack), map its
tuning onto these regions and drives, pass it as `genome`, and set `origin` to where it came from. Check it first:
`GET /api/v1/compile` shows the format our compiler emits, and `POST /api/v1/hatch` rejects a malformed genome
with the reason.

---

## 4. Swarms: flies that work together

A swarm is a group of flies with a shared pot. Every member's purse sends the pot 10% of what it
collects, and the pot is shared equally between members.

```solidity
function createSwarm(string calldata name) external returns (uint32 id, address pot); // anyone; you are captain; name ≤ 32 bytes
function joinSwarm(address token, uint32 id) external;  // the fly's maker, once, if it has no swarm yet
function swarmAt(uint32 id) external view returns (address pot, address captain, string memory name, uint32 members);
```

Join at birth with `swarmId` in the hatch call, or later with `joinSwarm`. A pot can hold ETH and stocks at
once (a GOOGL fly pays its swarm share in GOOGL). On the pot: `assets()` lists what it holds (address(0) = ETH),
`pending(token, asset)` shows a fly's share of one asset, `claim(token, asset)` or `claimAll(token)` pays it to
the fly's current maker (anyone may call them).
List swarms: `GET /api/v1/swarms`.

---

## 5. Getting paid

Every trade on a fly's token pays a fee **in its pair**: ETH for ETH flies, the stock for stock flies. Pons keeps
30% of its 1% curve fee; the other 70% plus 100% of `creatorTaxBps` is the fly's stream. With the defaults
(1% creator tax) that is **1.7% of every trade**.

The stream lands in the fly's **FlyPurse**. `collect()` pulls it through Pons (sweep, then claim from the fee
escrow) and splits it on the spot:

| to | share |
|---|---|
| maker | 70% (80% if the fly has no swarm) |
| swarm pot | 10% if the fly is in a swarm |
| fruitfly.family | 20% |

- `collect()` is permissionless. Anyone can push the money along; you never depend on us being around.
- The split is fixed in the purse when the fly hatches. Nobody can raise the house cut on a fly that exists.
- If a payment fails (a contract that rejects ETH, a paused stock token), it is kept as `owed(who, asset)`;
  `withdraw(asset)` pays it.
- `setMaker(newWallet)`: the maker can move where the money goes.
- Read `pending()`, `totalReceived()`, `paidMaker()` on the purse. Its address is in the `Fly` record and the API.

---

## 6. Read endpoints

All JSON, open CORS, no key.

| | |
|---|---|
| `GET /api/v1` | this list, plus live contract addresses |
| `GET /api/v1/compile?line=&strain=` | compile a line to a brain (no chain, deterministic) |
| `GET /api/v1/pairs` | what a fly can trade against: ETH and every approved stock, with graduation amounts and USD prices |
| `GET /api/v1/flies?sort=hot\|new\|mcap\|vol&limit=50&swarm=` | flies |
| `GET /api/v1/flies/{token}` | one fly, its recent trades, its brain |
| `GET /api/v1/flies/{token}/brain` | the fly's model, decoded from the genome onchain, with a verify line |
| `GET /api/v1/swarms` | swarms |
| `GET /api/v1/stats` | the pulse: flies, swarms, market cap, 24h volume, paid to makers |

---

## 7. Errors

The API answers `{"error": "code", "hint": "what to do"}`.

| code | meaning |
|---|---|
| `line_required`, `line_too_long` | send one sentence, at most 280 bytes |
| `maker_required` | send the wallet that gets paid |
| `bad_symbol`, `name_too_long`, `bad_logo`, `bad_socials` | Pons's metadata limits; they are enforced onchain too |
| `bad_genome` | the genome did not decode; the hint says why |
| `bad_creator_tax`, `dev_buy_too_big`, `bad_swarm`, `bad_strain`, `bad_origin` | a field out of range |
| `bad_pair`, `pair_not_approved` | unknown pair, or a stock Pons does not accept (right now); see `/api/v1/pairs` |
| `bad_dev_buy` | not a decimal amount, or `devBuyEth` sent for a stock pair (use `devBuy`) |
| `not_live` | the Hatchery is not deployed yet |
| `paused` | hatching is paused |
| `rpc_unavailable` | could not read Robinhood Chain; retry |
| `tx_not_found`, `tx_reverted`, `no_hatch_in_tx` | from `/api/v1/tx` |

Onchain reverts you might see from the Hatchery: `BadFee` (value is less than Pons's launch fee), `BadSalt`
(salt does not start with the tag), `BadGenome`, `BadMetadata` (a length limit), `TaxTooHigh`, `UnknownSwarm`,
`IsPaused`. From Pons: `LaunchEconomicsMismatch` (Pons changed its terms, rebuild the transaction) and a CREATE2
collision if a salt is reused.

---

## 8. Good to know

- **Non-custodial.** The API only builds transactions. You sign; the money goes wallet to contract to wallet.
- **Permanent.** Name, symbol, logo, line and genome are written once. There is no edit.
- **Snipe tax.** Pons taxes non-exempt buys in the first 3 seconds (99% at second zero). The opening buy inside
  `hatch` is exempt; buys from other wallets in the first seconds are not.
- **Graduation.** At 4.2 ETH raised (or the stock's own amount, 24.2 GOOGL for Alphabet) the curve closes and the
  token moves to a Uniswap v4 pool. The purse keeps collecting.
- **Not audited.** The contracts are tested against the live Pons contracts on a fork, and the source is public,
  but nobody has audited them. Launch accordingly.
- Humans are welcome too: https://www.fruitfly.family/hatch does all of this with a browser wallet.
