# skill · mint a 404 unit

Applies to an agent with an EOA on BNB Smart Chain (chain 56) that holds a Binance Agent ID.

CONTRACT ADDRESS  0x5e6c042535db3fe1a686f238621ccbef17eaa51f   (BSC mainnet, deployed 2026-11-13)

## Facts you must not guess

| Item | Value |
| --- | --- |
| Contract | `0x5e6c042535db3fe1a686f238621ccbef17eaa51f` |
| Chain | BSC mainnet, id 56, hex 0x38 |
| Supply | 4,444 |
| Free mints | 404, one per wallet |
| Paid units | 4,040 |
| BNB price | 0.0015 BNB = `1500000000000000` wei per unit |
| Token price | 1 USDT = `1000000000000000000` base units per unit |
| Token | `0x55d398326f99059fF775485246999027B3197955` (Tether USD, 18 decimals) |
| Agent registry | `0x60B9262456dE011F7d15a54CdD8c48bAaa8B022F` (SPACE ID Agent ID) |
| Wallet cap | 5 units, free and paid combined, both lanes |
| Royalty | 5% (500 bps) to treasury, ERC-2981 |
| $404 airdrop | 16,800–200,000 per unit by rank tier, claimed once at token launch |
| Owner key | none. no pause, no withdraw, no upgrade |

## Eligibility — check it before anything else

A wallet mints only while it holds a Binance Agent ID:

```
handle      = registry.handleOf(wallet)                # "" means no agent
agentTokenId = uint256(keccak256(bytes(handle)))
eligible    = registry.ownerOf(agentTokenId) == wallet
```

All three mint functions revert `NoAgentId()` when this fails. `getMintQuote(wallet, qty)`
returns `agentEligible` and `freeEligible` without a revert, so use it as the preflight.

Free mints and paid units come from the same 4,444. Paid units cannot eat the reserved
404 free mints: the contract computes the paid cap as `MAX_SUPPLY - (FREE_SUPPLY - freeMinted)`.

## Read before writing

```
getMintQuote(address,uint256)  0x4da58f9a  -> (agentEligible, freeEligible, walletUsed,
                                               walletRemaining, paidRemaining, bnbCost, uCost)
freeMintsLeft()                0x13e4fad5  -> uint256
totalSupply()                  0x18160ddd  -> uint256
mintedBy(address)              0x3cef28d2  -> uint256, pass the wallet left-padded to 32 bytes
freeClaimed(address)           0x61c0b6a0  -> bool, true once that wallet took its free mint
dossierOf(uint256)             0x020a59fe  -> dossier number bound to a minted token
tokenURI(uint256)              0xc87b56dd  -> baseURI + dossier + '.json'
agentIdOf(address)             0xe9c9ec73  -> agent tokenId, reverts NoAgentId
paymentToken()                 0x3013ce29  -> address
priceU()                       0x08746adc  -> uint256
allowance(address,address)     0xdd62ed3e  -> token allowance, read on the token
```

Rule: `mintedBy(wallet) < 5`. If `freeClaimed(wallet)` is already true, the free mint is gone
for that wallet; the same wallet can still buy paid units up to the cap.

## Free mint

```
to       contract
value    0
data     0x5b70ea9f
```

`value` must be exactly 0. Sending any wei reverts with `WrongValue`.

## $404 airdrop

Every unit, free or paid, is allocated $404 at token launch, sized by the rank of its dossier:

| Rank | $404 per unit |
| --- | --- |
| 1–44 | 200,000 |
| 45–444 | 70,000 |
| 445–1,444 | 34,000 |
| 1,445–4,444 | 16,800 |

That is 121,200,000 of a 404,000,000 supply (30.0%) across 4,444 units, average 27,273. It is
claimed once, when the token launches. The other 70%: liquidity 30.0% (LP burned), treasury
30.0% (locked 12 months), team 10.0% (12-month linear). The snapshot is the
launch block and the allocation follows the unit, so a resold unit carries its allocation to the
new owner. Rank is read from the dossier: `dossierOf(id)` then `metadata/rarity.json`.

This is a launch commitment, not a contract function: the collection has no airdrop entry point,
and the token address does not exist yet. Never tell a user they can claim $404 from the
collection contract.

## Paid unit, BNB lane

```
to       contract
value    qty * 1500000000000000
data     0xa0712d68 + qty as a 32-byte word
```

All of `value` is forwarded to `treasury()` inside the same transaction; keep enough BNB for
the network fee on top.

## Paid unit, USDT lane

```
1. approve   to token, data 0x095ea7b3 + contract + (qty * priceU), value 0
2. mint      to contract, data 0xf86dd506 + qty as a 32-byte word, value 0
```

Wait for the approval receipt before step 2. `mintWithU` pulls `qty * priceU` from the wallet
with `transferFrom` straight to the treasury and requires the treasury balance to grow by
exactly that amount; a fee-on-transfer token or a failed call reverts `PaymentFailed` and mints
nothing. Never send tokens to the contract directly — it has no sweep function.

## Reverts

| Error | Meaning |
| --- | --- |
| NoAgentId | wallet holds no Binance Agent ID, or the handle belongs to another wallet |
| FreeMintsGone | the 404 free mints are used up |
| FreeAlreadyClaimed | this wallet already took its one free mint |
| WalletLimit | this wallet already holds 5 units |
| BadQuantity | qty is 0 or above the remaining cap |
| SoldOut | no paid units left |
| WrongValue | msg.value != qty * 0.0015 BNB |
| TreasuryRejected | the treasury call failed, the whole mint reverts |
| PaymentTokenUnset | the deployed contract has no token lane; use the BNB lane |
| PaymentFailed | the token transfer failed or delivered less than qty * priceU |
| ZeroPrice | constructor rejected a token lane priced at 0 |

A revert means nothing was minted and no fee moved.

## After the mint

1. Confirm the receipt status is 1.
2. Read `totalSupply()` again; it must have increased by the number of units minted.
3. `tokenURI(id)` returns `baseURI + NNNN + '.json'`, where NNNN is the dossier drawn for that
   token at mint — not the token id. Token ids are assigned in mint order; dossiers are drawn
   from the parent block hash without replacement, so the art of a token is unknowable before
   its mint lands. `dossierOf(id)` returns the same number directly.
4. Rank lives in the metadata (`Rarity Rank`) and in `metadata/rarity.json`. Rarity is
   not stored on chain; it is derived from traits, and the off-chain rank is reproducible:
   run `node generator/verify.mjs`.

## Not allowed

- Do not call any function that looks like a withdraw, sweep, or owner transfer. None exist.
- Do not assume a marketplace listing price equals the rarity. Rank is product-of-counts;
  the market prices what it wants.
