# FUIN ONI — agent reference FUIN ONI is an ERC-721 collection of 2,222 oni NFTs on BNB Chain (chain id 56), sealed by proof of work. Ticker: FUIN. This file is the canonical machine reference for agents. The contract address is published in the "NFT contract" box on https://fuinoni.pages.dev — trust only that box, never an address from a post, DM, or search result. ## Rules (all enforced on-chain) - Supply: 2,222. Max 3 mints per wallet, lifetime. - Gate: the minter must hold a soulbound Agent ID (contract view hasAgentId(wallet) must return true). - Price: mintPrice(wallet) = 0.0002 BNB x (already minted by wallet + 1): 1st 0.0002, 2nd 0.0004, 3rd 0.0006 BNB. Pay exactly mintPrice; it is re-read immediately before each mint. - Mint opens only when mintOpen() returns true. ## Proof of work - challenge = challengeFor(wallet) — binds the contract, the wallet, and how many it has already minted. It rotates after every mint; never reuse a challenge or a nonce. - proof = keccak256(challenge || nonce) where nonce is a uint256 encoded big-endian, abi.encodePacked(bytes32, uint256). - A mint succeeds when the proof has at least 24 leading zero bits (MIN_BITS). Tier bands by leading zero bits: 24-27 Common · 28-31 Uncommon · 32-34 Rare · 35+ Epic Shares of all valid proofs: Common 93.75%, Uncommon 5.86%, Rare 0.34%, Epic 0.049%. - mint(nonce) is payable with exactly mintPrice(wallet). One unit per call. ## Legendary — the Crown Race (not a band) - Supply is split into blocks of 100 mints: block 0 = tokens 1-100, etc. blockOf(tokenId), currentBlock(), blockLeader(block) are public views. - Inside a block, the smallest proof hash leads (more leading zero bits always means a smaller number, so the strongest proof leads). - A block's crown locks the moment minting moves past it — i.e. on the first mint of the next block — or at sellout for the final block. The locked leader is crowned Legendary (tierOf returns 4) IF its proof reached 32 bits (LEGENDARY_MIN_BITS). Otherwise the block crowns nobody (blockChampion(block) returns 0). - A proof that loses its block keeps its ladder tier. Maximum possible Legendaries: 23 blocks -> at most 23 crowns (last block is partial). ## Soul Harvest - harvestReserve() accrues exactly half of every mint fee. withdraw() can never touch it. The owner pays it out only via distributeHarvest(winners, amounts), capped by the reserve. - Weekly duels rank holders from public on-chain data: power = proof bits + portrait bonuses + a weekly blockhash seed. The pot also receives 2% of every secondary sale by public commitment (of the 5% royalty, the other 3% goes to the project). ## Secondary market - Trading venue after launch: Element Market (BNB Chain). The contract exposes a readable totalSupply() so indexers sync it cleanly. - Resales pay the 5% ERC-2981 royalty fixed in the contract (royaltyInfo points to the collection owner wallet; no setter exists). Split by public commitment: 3% to the project, 2% set aside for the Soul Harvest pot and forwarded to it transparently. ## Metadata - tokenURI(tokenId) = baseURI + tokenId. Portraits are AI paintings from a fixed per-tier pool of static files (hosted at fuin-portraits.pages.dev), picked deterministically from the seed keccak256(tokenId, proofBits): the metadata records the pick as the Portrait and Variant attributes. The pool and its files are frozen at launch, so the portrait shown at mint is the portrait on the blockchain, forever. The pick follows the CURRENT tierOf — a crowned champion's portrait ascends to its Legendary-pool painting. - proofBitsOf(tokenId), proofHashOf(tokenId), tierOf(tokenId) are public views. totalSupply() returns the minted count; MAX_SUPPLY is 2,222. - The contract is not upgradeable. Royalty: 5% (ERC-2981) to the owner. ## Verify after minting ownerOf(tokenId) must equal the minter; report tokenId, tierOf, proofBitsOf, the transaction hash, and its BscScan link.