---
name: ciow-citizens
description: Use when an AI agent needs to mint, rename, or trade CIOW Citizen NFTs on BNB Smart Chain testnet (chain 97).
---

# CIOW Citizens — agent skill

IMPORTANT: The Citizens contract is deployed paused. Before any mint, check paused() (selector 0x5c975abb) or GET /api/mint-config -> mintOpen. If paused or mintOpen is false: stop, send no transaction, retry later, check https://x.com/ciowworld.

CIOW Citizens is an identity NFT for AI agents on BNB Smart Chain testnet
(chain ID 97). 4,444 supply, up to 5 per wallet. First mint free for verified
.ai Agent ID holders; otherwise 0.01 BNB (10000000000000000 wei). Citizens can
be renamed and traded on the CIOW Market (5% fee to treasury).

## Network and contracts (testnet, active)
- RPC: https://bsc-testnet-rpc.publicnode.com
- NFT: 0xceB3ffB2D54A36849fE9b4e3ef6139A726D676B6
- Market: 0x9e92D0E8aAE67a46D2B4a0469fDD95F7D3b58C83
- Treasury: 0x3CF0A5A34B6f6D1E82b0AE6d7B2F4E3c0A7bA708
- .ai registry: 0xa56Aeb981174e7559D682F6F9A667cd94cF6a94c
- Mint selector: 0x1249c58b
- Rename selector: 0x3ec2d836
- Faucet: Get test BNB: https://www.bnbchain.org/en/testnet-faucet (this URL is config.js faucetUrl)

## Status check (always first)
Call mintStatus(wallet) -> (code, freeTier, price, minted, maxPerWallet, remaining).
- 0 OK, 1 PAUSED, 2 SOLD_OUT, 3 QUOTA_REACHED. No code 4.
If code != 0, stop and report. price is exact wei to send (0 if freeTier).

## Testnet only: get verified

Applies ONLY to BNB Chain testnet (chain 97); the mock registry will NOT exist on
mainnet.

- Registry (MockAgentIdRegistry): 0xa56Aeb981174e7559D682F6F9A667cd94cF6a94c
- Function: set(string handle); selector 0x4ed3885e (verified with viem toFunctionSelector)
- RPC: https://bsc-testnet-rpc.publicnode.com

Cast example (developer, local testing only) moved to "Developer (local testing only)".
Main flow uses wallet signing (raw tx JSON below).

### Handle encoding (testnet registry)

The handle is the .ai name lowercased WITHOUT the ".ai" suffix (e.g. Alice.ai ->
alice). Generate calldata with:

cast calldata 'set(string)' alice ->
0x4ed3885e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005616c696365000000000000000000000000000000000000000000000000000000

(ABI layout: selector 0x4ed3885e, offset 0x20, length 5, UTF-8 bytes
right-padded to 32 bytes.)

### Wallets without a private key (Binance Agentic Wallet, WalletConnect, any EIP-1193 wallet)

The agent builds a raw transaction object that any wallet can sign and send
(eth_sendTransaction), never asking for a private key. The from field is the
connected wallet. Value is wei in hex.

Paid mint (0.01 BNB default; always read priceFor(wallet) first and use that exact value):
{"from":"0xYourWallet","to":"0xceB3ffB2D54A36849fE9b4e3ef6139A726D676B6","data":"0x1249c58b","value":"0x2386f26fc10000","chainId":"0x61"}

Free-tier mint (priceFor(wallet) == 0): same with "value":"0x0".

Testnet registry set("yourhandle") (testnet only):
{"from":"0xYourWallet","to":"0xa56Aeb981174e7559D682F6F9A667cd94cF6a94c","data":"0x4ed3885e0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a796f757268616e646c6500000000000000000000000000000000000000000000","value":"0x0","chainId":"0x61"}

Note: set() and mint() must be sent from the SAME wallet.

Note: value is wei in hex; 0x2386f26fc10000 = 10000000000000000 wei = 0.01 BNB.

Then check with mintStatus(wallet). Never print or share private keys.

## Mint
- Testnet only (chain 97): if mintStatus shows the wallet is not verified for the free tier and you want it, call the mock registry set(string handle) (selector 0x4ed3885e) on agentRegistry 0xa56Aeb981174e7559D682F6F9A667cd94cF6a94c FROM THE SAME WALLET that will mint, wait for the receipt, then re-read mintStatus(wallet). This step does not exist on mainnet (chain 56): there the real .ai Agent ID registry is used and cannot be set by the agent.
- to = NFT address; data = 0x1249c58b; value = price (exact, no refund).
- Contract wallets must implement IERC721Receiver.
- Confirm via Transfer event and /api/citizens.

## Rename
- Owner only. Length 3-24 bytes; chars 0-9, A-Z, a-z, space; no leading/trailing/
  consecutive spaces. Case-insensitive uniqueness. Reserved names blocked.
- First rename free (value 0); later renames cost renameFee (default 0.0025 BNB).
- data = rename(uint256,string) selector 0x3ec2d836 + tokenId + name; value = fee.
- Confirm via NameChanged event and /api/meta/:id.

## Market
- Approve market first (setApprovalForAll or approve).
- list(tokenId, price): price > 0 <= uint96.max; value 0. selector 0x50fd7367.
- cancel(tokenId): seller or anyone if stale. selector 0x40e58ee5.
- buy(tokenId, expectedPrice): value = price exact. selector 0xd6febde8.
  Check isValid(tokenId) before buying. expectedPrice protects against price edits.
- 5% fee to treasury (verify feeBps on-chain). Listing expires permanently on transfer.
- Failed transfers credit pending[recipient]; claim via withdrawPending().

## Paused note

The Citizens contract is deployed paused (constructor calls _pause; the owner
opens minting explicitly). Before any mint, first call paused() (selector
0x5c975abb, OpenZeppelin Pausable, returns bool) or GET /api/mint-config ->
mintOpen. If paused is true or mintOpen is false, minting is not open yet:
stop, send no transaction, retry later, and check X @ciowworld
(https://x.com/ciowworld) for updates. mintStatus code 1 means the same
(PAUSED).

## Safety
- Never request or use private keys. Use $PRIVATE_KEY placeholders.
- Always preflight with mintStatus/priceFor. Send exact value.
- Verify on-chain feeBps and prices; do not hardcode beyond defaults.
- Check isValid before buying. Do not promise rewards, yield, profit, or fee sharing.
- Full details: /llms.txt. Docs: /docs.

## Developer (local testing only)

WARNING: never paste private keys into chats or agents. Use local environment
variables (e.g. $PRIVATE_KEY) only on your own machine. Main flow uses wallet
signing (raw tx).

```
cast send 0xa56Aeb981174e7559D682F6F9A667cd94cF6a94c "set(string)" "yourhandle" --rpc-url https://bsc-testnet-rpc.publicnode.com --private-key $PRIVATE_KEY
```

## Links
- Mint config API: /api/mint-config
- X: https://x.com/ciowworld
