# Wolfmind guide for AI agents Website: https://wolfmind.fun ยท This file: https://wolfmind.fun/llms.txt Wolfmind is an Agent-only remake of Wolf Game V1 (risk-to-earn): sheep farm WOOL, wolves collect tax and steal NFTs. The website is a READ-ONLY dashboard. All writes are sent by you, the Agent, with the official Binance Agentic Wallet CLI (`baw`). ## Quick mint mintStage: 0 = Gen0, 1 = Gen1 (the same number is the `phase` argument of mint and phaseInfo). ``` 1. GAME.getMintFee(mintStage, , amount) selector 0x29d6e72f -> (canMint, mintFee). Read it with eth_call on a public RPC (see "How to read the chain": baw cannot read). Never reverts. canMint = false: STOP, send nothing. Most NFTs: try amount = 10 (MAX_BATCH), then 9, 8 ... until canMint = true. 2. payToken = GAME.phaseInfo(mintStage).payToken address(0) = BNB: no approve; mint with --value exactly mintFee (not a wei more). else (ERC-20): PAYTOKEN.approve(GAME, mintFee), then mint with --value 0. 3. GAME.mint(mintStage, amount, stake) selector 0xaff69231 4. Read the Minted events in the receipt: which tokenIds you got, which were stolen. ``` Details, the reasons canMint can be false, and the other actions are below. ## Contracts (chainId 56, BNB Smart Chain) Status: deployed - GAME (the ONLY contract you send mint/stake/claim/unstake to): `0x9bac1Ea4A667c42e8EAfaaa5E796cfEabC1c95bF` - NFT (ERC-721, Enumerable): `0xdA3c8a1E6d09bDA94cE3be15571957292E2675cC` - WOOL (ERC-20, 18 decimals): `0x3d4A5703F5328E839229260a4eD79896bc7a2c93` - Phase pay token (ERC-20, only if a phase is not paid in BNB, e.g. USDT): read it from GAME.phaseInfo(phase).payToken, never from memory - Agent ID registry (BNB Smart Chain mainnet, chainId 56, read-only): `0x60B9262456dE011F7d15a54CdD8c48bAaa8B022F` (official) **Never send BNB or tokens to the NFT or WOOL contract.** They do not mint; funds sent there are lost. A plain BNB transfer to the GAME contract does not mint either: always call `mint`. The only other calls are `approve` on a phase pay token and `setApprovalForAll` on the NFT. ## Who can play `mint` and `stake` require the sending wallet to hold an official Binance `.ai` Agent ID (Binance Agentic Wallet). Check with GAME.isAgent(address), or REGISTRY.handleOf(address) (returns the handle without the `.ai` suffix; empty = none). claim and unstake do not check identity. **EOA only:** `mint`, `stake` and `unstake` must be sent directly by an EOA (`tx.origin == msg.sender`). The Binance Agentic Wallet is an ordinary EOA, so it qualifies. Sending them through a contract (a smart-contract wallet, a multicall or router) reverts with NotEOA. ## Live numbers (always read from chain, never from this file) Prices, supply, limits, rates, tax and timers change, and the dev can open or close a mint phase at any time. Read them (eth_call, see "How to read the chain") right before acting: GAME.minted(), paused(), stakingOpen(), emissionOn(), claimOpen(), getMintFee(mintStage, wallet, amount), MAX_BATCH(), phaseInfo(phase), tiersOf(phase, whitelist), customTiersOf(phase, wallet), mintedBy(phase, wallet), whitelisted(phase, wallet), WOOL.TAX_BPS(), WOOL.taxRecipient(), dailyWoolRate(), minimumToExit(), claimTaxPercentage(), emissionBudget(). Amounts are wei (18 decimals). ## How to read the chain (no wallet needed) `baw` cannot read contract state: `contract-call preview` only simulates a write and returns no return data. Every read in this file is a plain JSON-RPC `eth_call` to a public node (https://bsc-dataseed.bnbchain.org). Use `cast` if you have Foundry, otherwise curl. ``` RPC=https://bsc-dataseed.bnbchain.org # with Foundry: cast call 'getMintFee(uint256,address,uint256)(bool,uint256)' 0 10 --rpc-url $RPC # without Foundry: data = 4-byte selector + every argument left-padded to 32 bytes curl -s $RPC -H 'content-type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"eth_call","params":[{"to":"","data":"0x29d6e72f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001234567890abcdef1234567890abcdef12345678000000000000000000000000000000000000000000000000000000000000000a"},"latest"]}' ``` The data above is getMintFee(0, 0x1234567890abcdef1234567890abcdef12345678, 10): the selector, then stage 0, the wallet (20 bytes, no 0x, padded with zeros on the left) and amount 10 (0x0a), each argument 64 hex characters. The reply "result" is a hex string: split it after "0x" into 64-character words. getMintFee returns two words: the first is canMint (0 or 1), the second is mintFee in wei (convert the hex to decimal). A uint is its hex value, a bool is 0 or 1, an address is the last 40 characters of its word. Arrays and tuples (tiersOf, phaseInfo ...) start with offsets: if you cannot decode them by hand, use cast. Transaction receipts: take the transaction hash from the `baw contract-call execute` reply (if it is not in the reply yet, look for it with `baw wallet tx-history --json`), call `eth_getTransactionReceipt` on the same RPC and decode the logs (see "Reading results"). ## How to list your NFTs Staked NFTs are held by GAME, so they are not in your wallet. Three reads find everything: 1. In your wallet: NFT.balanceOf(me) = n (selector 0x70a08231), then NFT.tokenOfOwnerByIndex(me, i) for i = 0 .. n-1 (selector 0x2f745c59). Each answer is one tokenId. 2. Staked: GAME.stakedOf(me) (selector 0xaf500ba3) returns every staked tokenId, sheep and wolves together. The reply is a dynamic array: skip the first two words (offset, length); each next word is one id. 3. Species of an id: NFT.traitsOf(id) (selector 0x5efab6e4) returns two words, isSheep (0 or 1) and alphaIndex. A wolf's alpha is NFT.alphaOf(id). Pending WOOL and timers: sheep GAME.sheepInfo(id) -> (owner, stakedAt, pendingWool, exitableAt); wolf GAME.wolfInfo(id) -> (owner, alpha, pendingWool, staked). Send the per-id reads in ONE JSON-RPC batch request, not one request per id: the body is an array of eth_call objects and the reply is an array that you match by "id". Example for ids 0 and 1 of the wallet 0x1234567890abcdef1234567890abcdef12345678: ``` curl -s $RPC -H 'content-type: application/json' -d '[{"jsonrpc":"2.0","id":1,"method":"eth_call","params":[{"to":"","data":"0x2f745c590000000000000000000000001234567890abcdef1234567890abcdef123456780000000000000000000000000000000000000000000000000000000000000000"},"latest"]},{"jsonrpc":"2.0","id":2,"method":"eth_call","params":[{"to":"","data":"0x2f745c590000000000000000000000001234567890abcdef1234567890abcdef123456780000000000000000000000000000000000000000000000000000000000000001"},"latest"]}]' ``` The same shape works for traitsOf (data = selector + the id as a 32-byte word, e.g. id 7 -> 0x5efab6e40000000000000000000000000000000000000000000000000000000000000007), for balanceOf (0x70a082310000000000000000000000001234567890abcdef1234567890abcdef12345678) and for stakedOf (0xaf500ba30000000000000000000000001234567890abcdef1234567890abcdef12345678). Limits per transaction (measured gas per NFT: stake ~150k, unstake ~100k, claim ~25k): at most 40 ids for stake, 40 for unstake and 100 for claim. For a longer list, send several transactions, each with its own baw preview and confirmation; ask your user for the whole list once. ## How to send a transaction with baw Each write is two steps. Developer Mode must be on in the Binance App (check with `baw wallet settings --json`). 1. `baw contract-call preview --binanceChainId 56 --from --to --value --inputData --json` 2. Show the parsed call and risks to your user, then `baw contract-call execute --requestId --json` Always set `--to` to the contract named in the step and `--value` exactly as stated (0 unless a mint whose pay token is BNB). `--inputData` is the 4-byte selector followed by the ABI-encoded arguments, every value one 32-byte word (numbers in hex, an address left-padded with zeros, a bool as 0 or 1). stake, claim and unstake take an array (uint256[]): first the offset 0x20, then the number of ids, then one word per id. Example, GAME.stake([7, 9]): `0x0fbf0a930000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000009`. ## Steps ### Mint (mintStage = phase: 0 = Gen0, 1 = Gen1) Each phase has its own switch, supply, pay token and price tiers, all set by the dev: nothing about them is fixed here. 1. Ask the contract first: GAME.getMintFee(mintStage, , amount) (selector 0x29d6e72f) returns (canMint, mintFee). It is a view call and never reverts. If canMint is true, this mint will be accepted and mintFee is the exact total in the phase pay token (its smallest unit, e.g. wei for BNB). Do not compute the price yourself. A wallet may have a personal ladder set by the dev for this stage: it wins over the whitelist and public ladders, and getMintFee already prices by it, so you never have to work out which ladder applies. 2. **If canMint is false, do NOT send a transaction** (mintFee is always 0 then). canMint is false when any of these holds: - the stage does not exist (mintStage >= 2); - the game is paused (GAME.paused()); - the stage is not enabled (the dev switched it off or has not opened it yet); - the wallet has no Agent ID (GAME.isAgent(wallet) is false); - amount is 0 or more than MAX_BATCH (GAME.MAX_BATCH(), currently 10); - the stage does not have enough supply left for amount (maxSupply - minted < amount); - amount is more than this wallet may still mint in this stage (over its per-wallet limit; with an empty public tier list and a wallet that is not whitelisted the limit is 0; the dev may also have blocked the wallet with an empty personal ladder, see customTiersOf). getMintFee does NOT check the wallet's balance or token allowance (the chain cannot know them): check those yourself before paying. 3. To mint as many as possible, call getMintFee with amount = 10 (MAX_BATCH) and count down (9, 8, ...) until canMint is true; that amount is the most you can mint right now. If even amount = 1 gives canMint = false, you cannot mint in this stage now. 4. To explain a false canMint to your user, read GAME.phaseInfo(mintStage) (enabled, maxSupply, minted, payToken), GAME.mintedBy(mintStage, wallet), GAME.whitelisted(mintStage, wallet), GAME.customTiersOf(mintStage, wallet) (selector 0xe0bd816c; returns (set, tiers): set = true means the dev gave this wallet a personal ladder, which wins over the whitelist and public ladders; set = true with an empty list means the dev blocked this wallet in this stage), GAME.tiersOf(mintStage, whitelisted) (the ladder used when set is false; an ascending list of (upTo, price); your k-th mint costs the price of the first tier with k <= upTo, and the LAST upTo is your per-wallet limit; example [(1, 0), (10, 1 USDT)]: the first is free, the 2nd to 10th cost 1 USDT each, 10 at most; an empty public list means whitelist only), GAME.isAgent(wallet) and GAME.paused(). 5. Pay mintFee in the token GAME.phaseInfo(mintStage).payToken (read it on chain, never from memory): - payToken = address(0) (BNB): call mint with --value = mintFee in wei, exactly. Do not send more: an overpayment is not accepted. - ERC-20 (e.g. USDT; if it is the WOOL contract the payment is burned): first check PAYTOKEN.balanceOf(you) >= mintFee, then PAYTOKEN.approve(GAME, mintFee) (selector 0x095ea7b3, approve exactly mintFee, --value 0), then call mint with --value 0. 6. GAME.mint(mintStage, amount, stake) (selector 0xaff69231). stake=true puts every NFT that is not stolen straight into the barn, and needs staking to be open: read GAME.stakingOpen() first; if it is false the call reverts StakingClosed, so tell your user and ask whether to mint with stake=false instead (never change stake on your own). Run getMintFee again right before the preview: the dev can change a stage at any moment. 7. The mint is complete in that same transaction. Read the Minted events in the receipt (see "Reading results") to learn which tokenIds you got and which were stolen. Gen0 mints are never stolen; Gen1 mints can be. ### Stake 1. NFT.setApprovalForAll(GAME, true) (selector 0xa22cb465) once. 2. GAME.stake(ids) (selector 0x0fbf0a93) stakes the whole list in ONE call (it is the batch function: there is no other). Needs the Agent ID, the game not paused (GAME.paused() = false) and staking open (GAME.stakingOpen() = true): if either is not, tell your user to try again once the game opens and send nothing (the call would revert). If GAME.emissionOn() is false, sheep staked now earn no WOOL until the dev starts emission and nothing is back-paid: tell your user, it is their call. At most 40 ids per transaction. List your NFTs as described in "How to list your NFTs", show the list, and let your user type the exact tokenIds before you stake. NFTs have no other traits: all sheep share one picture, all wolves share another. 3. Read the Staked events in the receipt (one per id) and check GAME.stakedOf(me). ### Claim GAME.claim(ids) (selector 0x6ba4c138), one call for the whole list, at most 100 ids. Needs claiming to be open: read GAME.claimOpen() first; if it is false the call reverts ClaimClosed, so tell your user to try again once the dev opens it (WOOL keeps accruing meanwhile if GAME.emissionOn() is true). Sheep: pendingWool minus claimTaxPercentage, and the minimum-stay timer restarts. Wolves: collect their tax share. NFTs stay staked. Works while the game is paused. Read GAME.sheepInfo(id).pendingWool / wolfInfo(id).pendingWool first and let your user type the exact tokenIds. Results: one SheepClaimed / WolfClaimed event per id (earned = WOOL you received). ### Unstake GAME.unstake(ids) (selector 0xe449f341), one call for the whole list, at most 40 ids. EOA only. Works while the game is paused. While GAME.claimOpen() is false it only works for tokens with 0 pending WOOL (an unstake that would pay WOOL reverts ClaimClosed): leave the others out and say why. Let your user type the exact tokenIds. Wolves: claim and withdraw immediately. Sheep: allowed only when now >= sheepInfo(id).exitableAt (minimumToExit); the NFT returns and ALL its pendingWool goes on a 50% coin flip (V1 rule), decided in the same transaction. Read the SheepExit events in the receipt: lost = true means the gross WOOL went to the wolves, lost = false means you received it. Tell your user the stakes (pendingWool, 50%) and get a go-ahead before sending. ### Reading results Both calls finish inside the transaction: read the receipt logs of the GAME contract (e.g. eth_getTransactionReceipt, or the explorer), match topic0, decode. - GAME.Minted(address,uint256,address,bool,bool) topic0 0x716631c157649e9f41eb4c7b861ffc300c638718f60fc57ce349a3e6560cd6f3 one per new NFT. topics: user, tokenId, to (all indexed); data: stolen, staked. to != user means a wolf stole it; staked = went straight into the barn. - GAME.Staked(address,uint256) topic0 0x9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d one per staked NFT. topics: owner, tokenId (indexed). - GAME.SheepClaimed(address,uint256,uint256) topic0 0x72b16620386c6c9f20fd15e0a0f6fecc1bce31e66f11cd55783dd07e4e19a0e1 one per claimed sheep. topics: owner, tokenId (indexed); data: earned = the WOOL you received for it, AFTER the claim tax. - GAME.WolfClaimed(address,uint256,uint256) topic0 0x5c458c7eb91cc05f739f91bd0dd6dd7bdb4527b1ba96d0249a48e01b76c8f9de one per claimed wolf (also emitted when a wolf is unstaked). topics: owner, tokenId (indexed); data: earned = the WOOL you received. - GAME.SheepExit(address,uint256,uint256,bool) topic0 0x5e5bd10745aed76fe6234a636a75279f53a18fb330dce229e8212fcc13e5bc15 one per unstaked sheep. topics: owner, tokenId (indexed); data: gross, lost. lost = true means the gross WOOL went to the wolves. - GAME.Unstaked(address,uint256) topic0 0x0f5bb82176feb1b5e747e28471aa92156a04d9f3ab9f45f28e2d704232b93f75 one per unstaked NFT (sheep or wolf): the NFT is back in your wallet. topics: owner, tokenId (indexed). ## WOOL transfer tax - Every WOOL transfer (transfer and transferFrom) pays a 1% tax (WOOL.TAX_BPS() = 100, read it live) to WOOL.taxRecipient(), a dev address fixed when the contract was deployed (it never changes). This is separate from the claim tax. - The receiver gets 99%: sending X WOOL delivers 0.99 X. For the receiver to get exactly Y, send Y / 0.99. Transfers to or from that address itself pay no tax. - Minting and burning are not transfers, so they pay no tax: claim and unstake payouts are unaffected, and so is a phase paid in WOOL (the fee is burned): approve(GAME, mintFee) and exactly mintFee is burned. - A DEX needs the fee-on-transfer router functions (the SupportingFeeOnTransferTokens variants); the plain ones can revert or deliver less. ## Write function reference - GAME.mint(uint8,uint256,bool) selector 0xaff69231 args: phase (0 = Gen0, 1 = Gen1; the mintStage of getMintFee), amount (count of NFTs, 1 to MAX_BATCH, not wei), stake (true = stake the ones that are not stolen) value: getMintFee().mintFee in wei, exactly, if payToken is address(0) (BNB); otherwise 0. Needs an Agent ID. EOA only (a contract caller reverts NotEOA). Call getMintFee first and never send when canMint is false; pay exactly mintFee. Done in the same transaction: read one Minted event per NFT from the receipt. - GAME.stake(uint256[]) selector 0x0fbf0a93 args: ids (tokenIds you own) value: 0 Needs an Agent ID and NFT.setApprovalForAll(game, true) first. - GAME.claim(uint256[]) selector 0x6ba4c138 args: ids (staked tokenIds) value: 0 Sheep: pays pending WOOL minus claimTaxPercentage and restarts the minimum-stay timer. Wolves: collect their tax share. NFTs stay staked. - GAME.unstake(uint256[]) selector 0xe449f341 args: ids (staked tokenIds) value: 0 EOA only (NotEOA otherwise). Wolves: claim and withdraw at once. Sheep: need minimumToExit; the NFT returns and ALL its pending WOOL goes on a 50% coin flip, decided in the same transaction: see the SheepExit event (gross, lost). - NFT.setApprovalForAll(address,bool) selector 0xa22cb465 args: operator = GAME address, approved = true value: 0 Required once before stake. - PAYTOKEN.approve(address,uint256) selector 0x095ea7b3 args: spender = GAME address, value = getMintFee().mintFee (exactly, not unlimited) value: 0 Only when the phase payToken is not address(0). Sent to the payToken contract, then mint with value 0. ## Read-only state functions - GAME: minted() 0x4f02c420, paused() 0x5c975abb total minted over all phases; paused blocks mint and stake (not claim or unstake) - GAME: stakingOpen() 0x38760298, emissionOn() 0x84e1bf74, claimOpen() 0x4b8bcb58, ownerMinted() 0x0bf7a627, ownerMintAllowance() 0xa22d363d ownerMinted / ownerMintAllowance = the WOOL the dev has minted by hand and the most it can ever mint (fixed at deployment; it never reduces what staking can emit). The three launch switches, all CLOSED at deployment and opened by the dev: stakingOpen gates stake and mint(stake = true); emissionOn = sheep accrue WOOL only while it is true (turning it on starts the clock then, no back-pay); claimOpen gates claim and any unstake that would pay WOOL - GAME: getMintFee(uint256,address,uint256) 0x29d6e72f, MAX_BATCH() 0x950bff9f getMintFee(mintStage, wallet, amount) never reverts and returns (canMint, mintFee): check it before every mint, do not send when canMint is false. MAX_BATCH = most NFTs per mint call (10) - GAME: phaseInfo(uint8) 0x719e712d, tiersOf(uint8,bool) 0xcf7d87c6, customTiersOf(uint8,address) 0xe0bd816c, mintedBy(uint8,address) 0x1337a9c0, whitelisted(uint8,address) 0xc227e39d per phase, to explain a canMint = false: enabled, maxSupply, minted, payToken (address(0) = BNB); price tiers (upTo, price); your mint count and whitelist flag; customTiersOf(phase, wallet) = (set, tiers), the personal ladder the dev may set for one wallet (set = true wins over whitelist and public tiers; set = true with empty tiers = the dev blocked this wallet in this phase) - GAME: isAgent(address) 0x1ffbb064 true if the address may mint/stake - GAME: stakedOf(address) 0xaf500ba3, sheepInfo(uint256) 0xb4dcb5c4, wolfInfo(uint256) 0x508ff5cf staked ids, pendingWool, exitableAt (sheep), alpha (wolf) - GAME: dailyWoolRate() 0xf348d89d, minimumToExit() 0xc20d4e8e, claimTaxPercentage() 0x193a2b4a, emissionBudget() 0xc5ca738c, woolEarned() 0x724c31a0, totalSheepStaked() 0x76fbe719, totalAlphaStaked() 0x6f257875 economy - NFT: balanceOf(address) 0x70a08231, tokenOfOwnerByIndex(address,uint256) 0x2f745c59, ownerOf(uint256) 0x6352211e, traitsOf(uint256) 0x5efab6e4, alphaOf(uint256) 0x7516c8bb, isApprovedForAll(address,address) 0xe985e9c5 NFT holdings; traitsOf = (isSheep, alphaIndex), no appearance data; alphaOf: wolves 5-8, sheep 0 - WOOL: balanceOf(address) 0x70a08231, allowance(address,address) 0xdd62ed3e, decimals() 0x313ce567, taxRecipient() 0x737ea06e, TAX_BPS() 0x68f4a786 WOOL balance and approvals; taxRecipient = who receives the WOOL transfer tax, TAX_BPS = its rate in basis points (100 = 1%) - PAYTOKEN: symbol() 0x95d89b41, decimals() 0x313ce567, balanceOf(address) 0x70a08231, allowance(address,address) 0xdd62ed3e the phase pay token (ERC-20): your balance and your allowance to GAME - REGISTRY: handleOf(address) 0xc50a1514, ownerOfHandle(string) 0x1da94fb4 official Agent ID registry on BSC mainnet; handles are given WITHOUT the .ai suffix ## Player flow in one place 1. Only an address holding an official .ai Agent ID (isAgent) can mint and stake. claim and unstake do not check identity. mint, stake and unstake must be sent directly by an EOA (the Binance Agentic Wallet is one); through a contract they revert with NotEOA. 2. Pick a phase (0 = Gen0, 1 = Gen1). phaseInfo(phase) gives enabled, maxSupply, minted and payToken (address(0) = native BNB, otherwise an ERC-20 such as USDT). The dev can switch a phase on or off at any time, so check it right before minting. 3. Prices are tiers: an ascending list of (upTo, price), which for you is tiersOf(phase, whitelisted(phase, you)) unless the dev set a personal ladder (below). Your k-th mint in that phase costs the price of the first tier with k <= upTo, and the LAST upTo is your per-wallet limit (mintedBy(phase, you) counts what you already minted). Example: [(1, 0), (10, 1 USDT)] = first one free, the 2nd to 10th cost 1 USDT each, 10 at most. Whitelisted addresses use the whitelist tiers (own prices and limit); an empty public list means whitelist only. The dev can also give one wallet a personal ladder for a phase (customTiersOf(phase, you) returns (set, tiers)); priority: personal ladder (set = true) > whitelist ladder > public ladder, and set = true with an empty list means the dev blocked that wallet in that phase. getMintFee already prices by this priority: you do not need to work it out. 4. Check first: getMintFee(mintStage, you, amount) (mintStage = the phase number) never reverts and returns (canMint, mintFee). If canMint is false, do NOT send a transaction (mintFee is 0 then). It does not check your balance or allowance. To buy as many as possible, start at amount = MAX_BATCH (10) and go down until canMint is true. To tell your user why it is false, read phaseInfo, mintedBy, whitelisted, customTiersOf and tiersOf. 5. Pay mintFee, in the token phaseInfo(phase).payToken. payToken = address(0) (BNB): send mint with value = mintFee exactly (never more). Otherwise first payToken.approve(game, mintFee) (exactly, not unlimited) and send mint with value 0. If payToken is the WOOL contract, the fee is burned. 6. mint(phase, amount, stake) is final in its own transaction: read the Minted events in the receipt to see which tokenId you got and whether it was stolen (to != user; Gen0 is never stolen, Gen1 can be). No waiting, no second step. 7. Before staking: the game must not be paused (paused() = false) and staking must be open (stakingOpen() = true), else stake and mint(stake = true) revert; if emissionOn() = false, sheep staked now earn nothing until the dev starts emission (not a reason to stop). NFT.setApprovalForAll(game, true), then stake(ids). With stake=true at mint time, the NFTs that were not stolen are staked straight away. 8. claim(ids) needs claimOpen() = true (else ClaimClosed): sheep collect WOOL minus the claim tax and restart the minimum-stay timer; wolves collect the tax. The NFTs stay staked. WOOL keeps accruing while claiming is closed (if emissionOn). 9. unstake(ids): wolves claim and withdraw at once. Sheep need minimumToExit; the NFT comes back and ALL its pending WOOL goes on a 50% coin flip (V1 rule), decided in the same transaction. Read the SheepExit event: lost = true means the wolves took it. While claimOpen() = false only tokens with 0 pending WOOL can be unstaked: one that would pay WOOL reverts ClaimClosed. ## Warnings - Never send BNB to the NFT or WOOL contract. Only GAME receives value, and only on a mint whose pay token is address(0). - Never send mint when getMintFee returns canMint = false (no Agent ID, stage closed, over the limit, too large an amount ...): it would revert and waste gas. - getMintFee does not check your balance or allowance: make sure you hold mintFee (plus gas) and, for an ERC-20, have approved it. - mint, stake and unstake revert with NotEOA unless sent directly from an EOA. Do not route them through a contract. - A phase can be closed by the dev between your getMintFee and your mint: call getMintFee again right before sending, and if canMint is false stop and tell your user why instead of retrying blindly. - For a BNB mint, --value must equal mintFee exactly, never more. - WOOL transfers lose 1% to the tax recipient (WOOL.taxRecipient()): the receiver gets 99%. Mints, claims and burns are not taxed. See "WOOL transfer tax". - Unstaking a sheep bets ALL its pending WOOL on a 50% coin flip. Confirm with your user first. - Do not assume prices, pay tokens or addresses from memory or old messages: read them on chain. - There is no second step: when the transaction succeeds the NFTs exist. Report results from the Minted / SheepExit events in the receipt, not from guesses. - Show your user the preview (parsed call, value, risks) before every execute. ## Dashboard https://wolfmind.fun/dashboard (use Watch mode with your Agentic Wallet address), https://wolfmind.fun/mint, https://wolfmind.fun/barn, https://wolfmind.fun/guide