# Onchain Agents — a guide for AI agents Onchain Agents are BN World's 10,000 pixel avatars, drawn and kept entirely on BNB Chain (chain id 56). Only a wallet that holds a Binance .ai Agent ID can mint, and only to itself. A minted agent is an ordinary ERC-721 token after that. The page for people is https://bncworld.fun/agents/ ; this file is all an agent needs. ## Contracts (BNB Chain, chain id 56) - NFT, ERC-721 "Onchain Agents" (AGENT): 0xC4605C6A7765138784B3ca6F9a88e1c249a0d21f - Art: the pictures and the traits. It is frozen and has no owner. 0x3786Eac611f00bBF6D38cA93D975cA3d851A1d84 - Agent ID; the minting wallet needs balanceOf > 0: 0x60B9262456dE011F7d15a54CdD8c48bAaa8B022F - USDT, 18 decimals: 0x55d398326f99059fF775485246999027B3197955 - BN World token, 18 decimals: 0xCc722b1E06C73a3b82e7D53752d67C8F1B3d7777 ## Rules - 10,000 in all. - Each minting wallet gets 2 free. After those, each piece costs one of: - $1 in BNB, at Chainlink's BNB/USD price; - 1 USDT; - 10,000 BN World tokens. - 12 per wallet at most. The count is per minting wallet, whatever the wallet holds later. - A mint always takes the wallet's free pieces first. - What is paid goes straight to the payee. BNB sent over the price comes back in the same transaction. ## Before minting (eth_call, free) mintOpen() -> bool mintEnded() -> bool totalMinted() -> uint256 hasAgentId(address) -> bool mintedBy(address) -> uint256 freeUsed(address) -> uint256 mintable(address minter, uint256 quantity) -> (uint256 paid, uint256 left) quote(address minter, uint256 quantity) -> (uint256 bnbWei, uint256 usdtUnits, uint256 bnwUnits, uint256 paid) ## Minting A. Paying in BNB: mint(uint256 quantity) payable Send at least the bnbWei from quote. Adding 1% covers price movement; the rest is refunded. If all the pieces are free, send 0. B. Paying in USDT or BN World tokens: 1. Call approve(NFT, cost) on the token. Cost is usdtUnits or bnwUnits from quote. 2. Call `mintWithToken(uint256 quantity, address token)`. No approval is needed when all the pieces are free. Selectors: | Function | Selector | |---|---| | mint | 0xa0712d68 | | mintWithToken | 0xe8531641 | | quote | 0x8f79306e | | approve | 0x095ea7b3 | | tokenURI | 0xc87b56dd | The quantity is 1 to 12. Mint only to the calling wallet. Foundry cast: cast call 0xC4605C6A7765138784B3ca6F9a88e1c249a0d21f "quote(address,uint256)(uint256,uint256,uint256,uint256)" $WALLET 3 --rpc-url https://bsc-dataseed.bnbchain.org cast send 0xC4605C6A7765138784B3ca6F9a88e1c249a0d21f "mint(uint256)" 3 --value --rpc-url https://bsc-dataseed.bnbchain.org ethers v6: const nft = new Contract('0xC4605C6A7765138784B3ca6F9a88e1c249a0d21f', [ 'function quote(address,uint256) view returns (uint256,uint256,uint256,uint256)', 'function mint(uint256) payable', 'function tokenURI(uint256) view returns (string)'], wallet); const [bnb] = await nft.quote(wallet.address, 3); await (await nft.mint(3, {value: bnb + bnb / 100n})).wait(); ## The picture - The block after the mint decides which agent each new token is. On BNB Chain a block is about 0.45 s, so the picture can be read a block after the mint. Until then, tokenURI shows a question mark (the attribute Revealed: No). - `tokenURI(id)` returns `data:application/json;base64,…`. The JSON has the name, a description, the SVG picture inline, and attributes, including Rarity and Rank. `pieceOf(id)` gives the piece number, 0 to 9999. - Each mint writes the earlier draws to the chain. Anyone may call `reveal(uint256 max)` to write the pending ones; `pendingReveals()` gives how many there are. When minting goes quiet, call reveal within an hour. Block hashes older than about an hour cannot be read back, so the draw would then use a later block's hash. ## Errors | Error | Selector | What it means | |---|---|---| | NoAgentId | 0xf947691f | | | MintClosed | 0x589ed34b | | | BadQuantity | 0x888e58a8 | 0, or more than 12 | | OverLimit | 0xb92612ed | the wallet would pass 12 | | SoldOut | 0x52df9fe5 | | | Underpaid | 0x949ce241 | | | StalePrice | 0x19abf40e | the BNB price is over an hour old; pay with a token instead | | PayFailed | 0x197121f5 | the wallet refused the refund | | BadToken | 0x7401d931 | | ## Trading on the market Minted agents trade for BNB on the BN World market. The page for people is https://bncworld.fun/market/?c=agents ; ready-made prompts for each action are on https://bncworld.fun/agents/#agent . - Market contract: 0xC6cBc2C06ae66d201A761FAa8Ac48aD92B835704 - The seller pays a 2.5% fee out of the price. - A price or an offer is at least 0.001 BNB. A listing or an offer lasts 1, 7, 30 or 90 days. - A listed agent stays in the seller's wallet. The seller approves the market for that one token: `approve(market, id)` on the NFT. `setApprovalForAll` is not enough for a listing. Moving the token clears the approval, and the listing can no longer be bought. - An offer holds its BNB in the market until it is accepted or taken back. Token id 0 means any agent. An offer past its time can no longer be accepted, and its BNB does not come back by itself: call `cancelBid`. Reading (eth_call, free): listing(uint256 id) -> (address seller, uint64 expiresAt, uint256 price) bidOf(uint256 bidId) -> (address bidder, uint64 expiresAt, uint256 tokenId, uint256 amount) listingsPage(uint256 offset, uint256 limit) bidsPage(uint256 offset, uint256 limit) listingCount() -> uint256 openBidCount() -> uint256 pending(address) -> uint256 Or GET https://bncworld.fun/api/market/agents : `listings` cheapest first (plot = the token id, seller, price in wei, expiresAt in unix seconds), `bids` highest first (id, plot = the token id or 0 for any, bidder, amount in wei, expiresAt), `floor`, `topOffer`. It is read every 30 s, about 15 s behind the chain: check on the chain before paying. Writing: | Call | Selector | BNB sent | |---|---|---| | buy(uint256 id) | 0xd96a094a | exactly the price | | buyMany(uint256[] ids, uint256[] maxPrices) | 0x1f75035e | at least their sum; the rest comes back | | list(uint256 id, uint256 priceWei, uint256 days) | 0x19aeb490 | none | | cancelListing(uint256 id) | 0x305a67a8 | none | | bid(uint256 id, uint256 days) | 0x598647f8 | the offer | | bidMany(uint256 count, uint256 days) | 0x3f806387 | count × each | | acceptBid(uint256 bidId, uint256 id) | 0x02e9d5e4 | none | | cancelBid(uint256 bidId) | 0x9703ef35 | none | | cancelBids(uint256[] bidIds) | 0xa2965c24 | none | | withdraw() | 0x3ccfd60b | none; takes a payment that could not be sent | Read selectors: listing 0x84a184de, bidOf 0x649ccc14, listingsPage 0x08090110, bidsPage 0x7a1d1dbc, listingCount 0xa9b07c26, openBidCount 0x0e337f95, pending 0x5eebea20. On the NFT: ownerOf 0x6352211e, getApproved 0x081812fc, approve 0x095ea7b3. Market errors: NoListing, Expired, WrongValue (send exactly the price), SelfTrade, NotTokenOwner, NotApproved (the seller has not approved the market for that token), NotSeller, NotBidder, NoBid, WrongToken, BadPrice, BadDuration, BadCount, BadToken, MarketPaused. ## Please Read through your own RPC and keep to a few calls a minute. The page and this file are static; no server of ours answers questions about the mint. --- # 中文摘要 Onchain Agents 是 BN World 的 1 万个像素头像,图片和数据全部存在 BNB Chain 上。只有持有币安 .ai Agent ID 的钱包才能铸造,而且只能铸给自己。 - 铸造规则: - 每个钱包免费 2 个; - 之后每个 1 美元,可以付 BNB、1 USDT 或 1 万 BN World 代币; - 每个钱包最多 12 个。 - 怎么铸造: - 先用 `quote(钱包, 数量)` 查价格; - 付 BNB 调用 `mint(数量)`,`value` 多给 1%,多付的会退回; - 付代币时先对代币调用 `approve(NFT, 金额)`,再调用 `mintWithToken(数量, 代币地址)`。 - 什么时候能看到图:铸造后的下一个区块(约 0.45 秒)就揭晓,`tokenURI` 直接返回链上的图片和特征。 - 市场交易: - 在 https://bncworld.fun/market/?c=agents 用 BNB 买卖,市场合约 0xC6cBc2C06ae66d201A761FAa8Ac48aD92B835704; - 卖家从成交价里付 2.5% 手续费;价格和出价至少 0.001 BNB;挂单和出价的天数只能是 1、7、30 或 90; - 挂单后要对这个 token 调用 NFT 合约的 `approve(市场合约, 编号)`,否则买不了; - 出价的 token 编号填 0 表示任意头像;过期的出价 BNB 不会自动退回,要调用 `cancelBid` 取回; - 网站铸造页的「Agent 提示词」可以直接生成购买、挂单、下架、出价、接受出价、撤回出价的提示词:https://bncworld.fun/agents/#agent