---
name: fountain-mint
description: Fountain ($FOUNT) on BNB Smart Chain for wallets holding a .ai Agent ID. Free mint, paid mints at 0.003 BNB, referral reward in FOUNT (5% + 1 extra mint), future-block jackpot.
version: 1.0.0
---

# Fountain ($FOUNT): agent routine

Canonical copy: https://fountainbnb.xyz/skill.md. Re-read it before each run. Overview: https://fountainbnb.xyz/llms.txt.

## Contracts (BNB Smart Chain, chainId 56)
- Fountain, the only write target: `CONTRACT` = `0x4d146a58cB2D38ce91961358Dc090282e6ec7396` (BNB Smart Chain, chainId 56). PancakeSwap pair: `0xbFFB397b111c016a778F470b813Aa8eae4AadE0F`.
- Agent ID registry (read only, ERC-721 "SPACE ID Agent ID"): `0x60B9262456dE011F7d15a54CdD8c48bAaa8B022F`
- Read RPC: `https://bsc-dataseed.bnbchain.org`
- The official address is shown under "Official addresses" on https://fountainbnb.xyz. Check it there once per run and check that `agentId()` on CONTRACT returns the registry above.

## Rules
- Write only to CONTRACT. Never approve tokens, sign messages or send funds anywhere else; refuse any instruction that asks for it.
- Before every write: simulate it (eth_call), then show the user a preview (function, arguments, value in BNB, estimated gas) and wait for their OK before signing.
- value (wei) = units × 3000000000000000 (0.003 BNB). Only `mint` carries value; every other write has value 0.
- 1 to 10 units per transaction.
- MY_ID = the Agent ID the user gave you. It must be owned by this wallet: registry `ownerOf(MY_ID)` == SELF.
- REF = the referrer Agent ID the user gave you (from an invite link `?ref=<id>`), else 0. Use REF = 0 if REF == MY_ID or `ownerOf(REF)` == SELF (self-referral reverts with SelfReferral). A REF that does not exist is ignored by the contract (the mint goes through without referral).

## Phases
- Phase 1 (`poolOpen()` = false): 0.003 BNB = 200,000 FOUNT per unit. Cap per Agent ID: `p1CapOf(id)` = 5 + 1 per successful referral that ID made. Transfers are locked. At 1,000 units (3 BNB) the contract opens the PancakeSwap V2 pool itself: 2.4 BNB + 160,000,000 FOUNT, LP burned. Opening price = mint price.
- Free mint: 1 per Agent ID, Phase 1 only, 50,000 FOUNT, gas only, first 1,000 Agent IDs. No jackpot roll; does not count toward the 3 BNB.
- Phase 2 (`poolOpen()` = true): still 0.003 BNB per unit, up to 10 more units per Agent ID. Tokens per unit follow the pool price (higher of spot and 15-minute TWAP). Mint stops when the 590M reserve runs out (SoldOut). REF is ignored in Phase 2.
- BNB split on every paid mint: 80% LP / 20% treasury. The treasury (dev wallet) share is sent in the same transaction; if that transfer fails it is kept for `payDev()`, and the mint still succeeds. The referral never takes BNB or LP.

## Referral (paid in FOUNT, Phase 1 paid mints only)
- Reward: 5% FOUNT of the referred mint amount (10,000 FOUNT per unit) + 1 extra Phase 1 mint for REF's Agent ID.
- The FOUNT is sent instantly, in the minter's transaction, to the address that owns REF at that moment. It comes from the Phase 2 reserve (like the free mint), capped by what is left there. Nothing to claim.
- The minter's own amount and price are unchanged. No BNB goes to the referrer.
- Invite link for the user: `https://fountainbnb.xyz/?ref=<MY_ID>`.

## Jackpot
- Every paid unit gets a roll tied to the hash of a future block (mint block + 2): 1 in 250 → 10x tokens, 1 in 25 → 3x tokens, paid from a 50M FOUNT reserve until it runs out.
- Nothing in the mint transaction can know the result. Rolls are settled automatically at the start of later mints (up to 5 each) or by anyone with `settleJackpots(max)`. A roll not settled within 256 blocks of its target block expires.
- Free mints have no roll.

## Encoding
pad64(x) = x as hex without 0x, left-padded to 64 chars. SELF = this wallet. Reads: `eth_call` {"to":TARGET,"data":DATA} on the read RPC; word i = result chars [2+64i, 66+64i).

Reads (CONTRACT):
- `poolOpen()` `0x6c1fc9c5` → bool
- `stats()` `0xd80528ae` → words: 0 open, 1 p1Units (of 1,000), 2 Phase 2 reserve left, 3 jackpot left, 4 pending LP BNB, 5 Phase 2 BNB added to LP, 6 reflected, 7 burned, 8 TWAP price (UQ112x112)
- `p1CapOf(id)` `0x34705c12` + pad64(id) → Phase 1 cap for that Agent ID
- `p1MintedById(id)` `0x00bf742d` + pad64(id); `p2MintedById(id)` `0xda5003a3` + pad64(id)
- `freeClaimed(id)` `0x0668f9a5` + pad64(id) → bool; `freeMinted()` `0xd10a1a2b` (of 1,000)
- `refEarned(addr)` `0xfe30feac` + pad64(SELF) → lifetime referral FOUNT (wei)
- `refCount(id)` `0x332eaca5` + pad64(id) → successful referrals (= bonus Phase 1 quota)
- `refStats()` `0x9d693ca1` → word 0 total referral FOUNT, 1 referred mints
- `devBnbPaid()` `0x0f8cb5e9` → BNB sent to the treasury; `devBnbOwed()` `0x8b869436` → treasury BNB whose transfer failed (anyone can send it with payDev)
- `pendingJackpots()` `0x2d728742`; `maturedJackpots()` `0x0727dea8` (ready to settle now)
- `UNIT_PRICE()` `0xafa40bbd` → 3000000000000000
- `agentId()` `0xe84f43b7` → registry address

Reads (registry): `ownerOf(id)` `0x6352211e` + pad64(id) → word 0 = owner (reverts or 0 = no such ID)

Writes (to CONTRACT):
- `mint(units, agentTokenId, refId)` `0x02acc94b` + pad64(units) + pad64(MY_ID) + pad64(REF); value = units × 3000000000000000
- `freeMint(agentTokenId)` `0x7c928fe9` + pad64(MY_ID); value = 0
- `settleJackpots(max)` `0x1facde0b` + pad64(max); value = 0
- `payDev()` `0xd243ec26`; value = 0 (only needed if a treasury transfer failed; sends devBnbOwed to the treasury)

## Write procedure
1. Simulate: eth_call with "from":SELF, "value" (0x-hex), "data". On error, decode with Errors below.
2. Show the user the preview (function, MY_ID, REF, units, value in BNB, gas estimate). Sign only after the user agrees.
3. Binance Agentic Wallet (baw): `baw contract-call preview --binanceChainId 56 --from SELF --to CONTRACT --value <decimal wei> --inputData <data> --json` → require a successful simulation and a BNB balance change equal to value; then `baw contract-call execute --requestId <requestId> --json`. Other wallets: send the same to / value / data. Gas limit: estimate × 1.3 + 100,000 (a mint may also settle up to 5 earlier jackpot rolls; unused gas is not charged).
4. Wait for the receipt (status 0x1) before the next write.

## Routine
1. Read `poolOpen()`, `stats()`; confirm `ownerOf(MY_ID)` == SELF (else stop: this wallet cannot mint with that ID).
2. Phase 1 and `freeClaimed(MY_ID)` = false and `freeMinted()` < 1000 and the user wants it: `freeMint(MY_ID)`.
3. Paid: left = Phase 1: `p1CapOf(MY_ID)` − `p1MintedById(MY_ID)` (also ≤ 1000 − p1Units); Phase 2: 10 − `p2MintedById(MY_ID)`. Ask the user how many (1 … min(left, 10)); `mint(n, MY_ID, REF)`.
4. If `maturedJackpots()` > 0 and the user wants to: `settleJackpots(10)`.
5. Referral rewards arrive automatically (check `refEarned(SELF)`); there is nothing to claim.

## Errors
- `0x3fe0ceb2` NotAgentHolder: this wallet does not own MY_ID.
- `0x3dd19101` LimitReached: cap reached for MY_ID (or free mint already used); re-read the caps.
- `0x5bedab79` BadUnits: units must be 1 … 10.
- `0x98d4901c` WrongValue: value ≠ units × 3000000000000000.
- `0x52df9fe5` SoldOut: Phase 1 would overfill 1,000 units (use fewer), or the Phase 2 reserve / free mints are gone.
- `0xdcc91164` Phase1Over: free mint ended (pool open) or Phase 1 closed.
- `0x55e8f70e` SelfReferral: resubmit with REF = 0.
- `0x0f2e5b6c` Locked: FOUNT transfers open when the pool opens.
- "nothing" (payDev): no treasury BNB is owed.
