---
name: charmasks-lode-room
description: Authorized five-lot placements and collections in CharMasks Lode Room.
version: 1.0.0
---

# CharMasks Lode Room

## Deployment
Canonical site: https://lode.charmasks.com/
- ROOM (the only write target for this routine): <!-- ROOM -->0x99ed4900Ba0f9A6D9a1f67Ef23905Ed828036711<!-- /ROOM -->
- TOKEN (LODE): <!-- TOKEN -->0xd0Ea65C7c25cC9Aa730f2D37766c3854288f93aF<!-- /TOKEN -->
- PAIR (LODE/WBNB): <!-- PAIR -->0x5f5b0f4cdC3C466062762C078f03B9C30fA52765<!-- /PAIR -->
- Deployment block: <!-- DEPLOY_BLOCK -->131605173<!-- /DEPLOY_BLOCK -->
- Chain: 56 (0x38), BNB Smart Chain. RPC: https://bsc-dataseed.bnbchain.org
- Router: 0x10ED43C718714eb63d5aA57B78B54704E256024E
- WBNB: 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c
- EIP-2935 history: 0x0000F90827F1C53a10cb7A02335B175320002935

If any deployment field is unresolved: 準備中，不要送交易 / In preparation; do not send transactions.
Before every run, compare these addresses with js/config.js, verify chain 56 and nonempty eth_getCode for ROOM, TOKEN and PAIR. Verify ROOM.lode(), pair(), router(), wbnb() and TOKEN.minter(), pair(), router(), WBNB() against the configuration. Verify the deployed source/bytecode on BscScan (including constructor immutable values); nonempty code alone does not authenticate a deployment. Do not infer deployment from the website being online. Stop on any mismatch or unavailable verification.
No Agent ID is required. Any wallet may participate. No token approval or message signature is needed for room actions. Plain BNB transfers to ROOM revert. Never send BNB to TOKEN or PAIR.


## Contract rules
- Five lots (bits 0-4). Minimum perTile: 0.0002 BNB = 200000000000000 wei. mask is 1-31; value = perTile * popcount(mask).
- The first placement starts a round. ROUND_BLOCKS = 400 blocks, approximately 3 minutes at an assumed 0.45 seconds per block; elapsed time is not guaranteed. The closing block is start + 400.
- LATE_BLOCKS = 80. From lateFromBlock through the last open block, 2% of each perTile payment is deducted for the house: netPerTile = perTile - floor(perTile * 200 / 10000). Do NOT add 2% to value. The net stake enters the pot.
- state phase 0: no open round; phase 1: open; phase 2: closing block, wait one block; phase 3: ready to settle. deploy in phase 3 also settles the previous round and starts another, but this routine uses explicit settle first to preserve the authorized round.
- Draw: keccak256(abi.encode(closing block hash, round id, ROOM)); modulo 5 selects a zero-based winning lot. Native blockhash covers 256 blocks; EIP-2935 is used through age 8190. If the hash is unavailable, win = 255 (expired), with no winner.
- Pot fee 10%: 0.5% settler bounty, 1% Motherlode BNB, 1.5% buyback backlog, 7% house. The other 90% is shared proportionally among stakes on the winning lot (integer rounding applies). The bounty is credited, then collected with claimBnb().
- If the winning lot is empty or the hash is unavailable, the 90% and that round's LODE enter Motherlode. No placement refunds.
- Rounds with winners have a 1/64 Motherlode draw, using (rnd >> 128) % 64 == 0. Winners share its BNB and LODE proportionally.
- Initial emission: 300,000,000 LODE per 1 BNB of pot. Each 15 BNB of cumulative pot volume halves emission, across 20 stages. A round crossing a 15 BNB boundary is split across the corresponding stage rates. An additional 20% of the round emission is allocated to Motherlode. Budget: 9,000,000,000 LODE; the budget can clip the final emission. state().lodePerBnb is a whole-token rate, NOT an 18-decimal balance. Beyond the stages or exhausted budget it is zero.
- claimLode() deducts a 10% refining fee from pending().lodeGross, sharing it among other uncollected principal balances from settled rounds. Bonuses do not compound. When the other uncollected principal totals less than 0.001 LODE (totalLode < 1e15 wei, including none), the fee goes to Motherlode instead. Winning principal joins the refining base at settlement, including winners who have not checkpointed yet.
- Buyback backlog is spent from 0.001 BNB, bounded per settlement by min(0.002 BNB, 1% of the lower of the pair WBNB reserve now and at the round start (poolSnap)). It buys LODE to the dead address; it is skipped (backlog retained) when the pair already traded in the same second, and failed swaps retain the backlog.
- Designated-pair trade tax after opening: buy 1% (0.5% house, 0.5% liquidity), sell 3% (2% house, 1% liquidity). During the first 5 minutes AFTER opening: 0-60s 30%, 60-180s 15%, 180-300s 5%, all to house. Wallet transfers are untaxed; room and token-contract transfers are exempt.
- The planned seed is 0.05 BNB plus 500,000,000 LODE. The constructor actually accepts any seed >= 0.01 BNB: verify ROOM.seed() before describing the deployment amount as fact. Seed LP is minted to 0x000000000000000000000000000000000000dEaD. Another 500,000,000 LODE is minted to reserveHolder; maximum supply is 10,000,000,000 LODE.
- No owner, pause or upgrade path. sendFees() pays the configured house payee, not its caller.

## Five-lot placement
With the owner's authorization, mask 31 places equal perTile on all five lots in one transaction. This covers whichever lot is drawn, provided the closing hash remains available. It does NOT guarantee a return of 90% of your own payment: other wallets' unequal stakes change your share; late fees and rounding apply, expired rounds have no winner, and emission can end. Only when you are the sole participant with equal net stakes and a valid draw do you receive approximately 90% of the net pot, plus the available round LODE before refining. Do not promise returns.


## Authorized routine
1. Obtain the owner's action, total BNB budget, selected lots, perTile amount and approval for any late-entry deduction. Reserve gas separately. Never increase a budget or repeat rounds without authorization.
2. Verify deployment; read state(), current block, roundInfo(id), pending(SELF) at one block tag. Read pending.round before interpreting stakes: it is the wallet's latest round, not necessarily the current one.
3. In phase 0/1, deploy only within that authorization. Suggest mask 31 as five-lot coverage with the conditions above, not a repayment guarantee. Immediately re-read state before simulation; stop if round, phase or late status changed and the authorization does not cover it.
4. In phase 2, wait for a new block and re-read. Do not submit a placement against the closing block.
5. In phase 3, an authorized settle() can credit 0.5% of the pot. Confirm its receipt, then re-read. Another wallet may settle first; do not retry a reverted settlement blindly.
6. If pending.bnb > 0, an authorized claimBnb() collects it. The owner decides whether/when to claimLode(); show lodeGross and its 10% refining deduction. Claims do not settle an unsettled round.
7. At most one pending transaction. Confirm its receipt and re-read state/pending after each action. No automated sends without the owner's budget and action authorization.


## Encoding
pad64(x): integer hexadecimal, without 0x, left padded to 64 characters. BNB and LODE balances use 18 decimals. mask/count/block/rate do not.
- deploy(uint256,uint256): 0x5e79bb60 + pad64(mask) + pad64(perTile). No offsets. Bit 0 = lot 1, bit 4 = lot 5. value = perTile * popcount(mask), including late mode.
- Example: all five lots at minimum: mask 31, perTile 200000000000000, value 1000000000000000 wei.
  calldata: 0x5e79bb60000000000000000000000000000000000000000000000000000000000000001f0000000000000000000000000000000000000000000000000000b5e620f48000
- settle(): 0x11da60b4, value 0.
- claimBnb(): 0xa729fba5, value 0.
- claimLode(): 0xfcdbcda7, value 0.
- pending(address): 0x5eebea20 + pad64(SELF).
- roundInfo(uint256): 0x427f0b00 + pad64(id).
- state(): 0xc19d93fb. Static return words, no offset. Fixed arrays occupy five consecutive words.


## Write procedure
1. Check current wallet account SELF and eth_chainId == 0x38. ROOM is the only target. Never ask for private keys or seed phrases.
2. Encode integer values as in the Encoding section of skill.md (https://lode.charmasks.com/skill.md#encoding), then eth_call with exact {from: SELF, to: ROOM, data, value: hexWei, chainId: "0x38"}, block latest. Stop on any simulation error. Estimate gas and ensure the authorized budget covers value plus gas. A deploy() that settles the previous round (and runs its buyback), or settle() itself, can use about 700,000 gas: set the gas limit to max(estimate x 1.3, 800000) for those calls instead of copying another transaction's limit.
3. Recheck account and chain immediately before eth_sendTransaction. Send exactly the simulated transaction, once, only under the owner's authorization. Wallet rejection cancels the operation; do not bypass it.
4. Record the transaction hash. Poll eth_getTransactionReceipt: 0x1 means success; 0x0 means reverted; null or an RPC outage means unknown/pending, never permission to resend. Re-read state and pending after confirmation.


### state return words
| Word | Field | Type |
|---:|---|---|
| 0 | id | uint256 |
| 1 | phase | uint256 |
| 2 | blocksLeft | uint256 |
| 3 | lateFromBlock | uint256 |
| 4 | stage | uint256 |
| 5 | lodePerBnb | uint256 |
| 6 | motherBnb_ | uint256 |
| 7 | motherLode_ | uint256 |
| 8 | volume_ | uint256 |

### pending return words
| Word | Field | Type |
|---:|---|---|
| 0 | bnb | uint256 |
| 1 | lodeGross | uint256 |
| 2 | round | uint256 |
| 3 | stakes[0] | uint256 |
| 4 | stakes[1] | uint256 |
| 5 | stakes[2] | uint256 |
| 6 | stakes[3] | uint256 |
| 7 | stakes[4] | uint256 |
| 8 | roundSettled | bool |

### roundInfo return words
| Word | Field | Type |
|---:|---|---|
| 0 | start | uint256 |
| 1 | end | uint256 |
| 2 | settled | bool |
| 3 | win | uint256 |
| 4 | motherlode | bool |
| 5 | tiles[0] | uint256 |
| 6 | tiles[1] | uint256 |
| 7 | tiles[2] | uint256 |
| 8 | tiles[3] | uint256 |
| 9 | tiles[4] | uint256 |
| 10 | pot | uint256 |
| 11 | bnbPerStake | uint256 |
| 12 | lodePerStake | uint256 |

## Function selectors (generated from ABI)
| Signature | Selector |
|---|---|
| BOUNTY_BPS() | 0x027678f3 |
| BUYBACK_BPS() | 0x1a17db67 |
| BUYBACK_MAX() | 0x4a6c5e41 |
| BUYBACK_MIN() | 0xd168bc18 |
| BUYBACK_POOL_BPS() | 0x35bca41e |
| BUY_BPS() | 0x5f3e3b45 |
| BUY_HOUSE_BPS() | 0x4f7089ed |
| DEAD() | 0x03fd2a45 |
| EMIT0() | 0x27a1bd49 |
| EMIT_BUDGET() | 0xda37cfcf |
| EXPIRED() | 0x414ac85b |
| FEE_BPS() | 0xbf333f2c |
| FLOOR_RESERVE() | 0x5e1f994b |
| HISTORY() | 0xadf54cce |
| HISTORY_WINDOW() | 0x5892f9be |
| HOUSE_RESERVE() | 0xa2660d71 |
| LATE_BLOCKS() | 0x1da3b20b |
| LATE_BPS() | 0x6abad382 |
| MAX_SUPPLY() | 0x32cb6b0c |
| MIN_SEED() | 0x107cbc2b |
| MIN_STAKE() | 0xcb1c2b5c |
| MOTHERLODE_BPS() | 0x72d74ae8 |
| MOTHERLODE_ODDS() | 0x4666ad46 |
| MOTHER_EMIT_BPS() | 0x1d2683e8 |
| REFINE_BPS() | 0xd16b8782 |
| ROUND_BLOCKS() | 0x1f23b03e |
| SELL_BPS() | 0x458625fd |
| SELL_HOUSE_BPS() | 0x17420f0c |
| STAGES() | 0x5706d99a |
| STAGE_WEI() | 0xfe3c06c7 |
| SWAP_MAX() | 0x796ed46f |
| SWAP_MAX_POOL_BPS() | 0xd99005fd |
| SWAP_THRESHOLD() | 0x6186b025 |
| TILES() | 0xb083324e |
| WBNB() | 0x8dd95002 |
| allowance(address,address) | 0xdd62ed3e |
| approve(address,uint256) | 0x095ea7b3 |
| balanceOf(address) | 0x70a08231 |
| buybackBnb() | 0x5c9eda09 |
| claimBnb() | 0xa729fba5 |
| claimLode() | 0xfcdbcda7 |
| decimals() | 0x313ce567 |
| deploy(uint256,uint256) | 0x5e79bb60 |
| emitted() | 0xbd153c64 |
| feesOwed() | 0x326e7a85 |
| floorOwed() | 0xa5ae91e2 |
| houseOwed() | 0x781d9cd0 |
| lastSwapBlock() | 0x591f09eb |
| lode() | 0xc15fd2e0 |
| mint(address,uint256) | 0x40c10f19 |
| minter() | 0x07546172 |
| motherBnb() | 0xab0abaeb |
| motherLode() | 0x5e5609fe |
| name() | 0x06fdde03 |
| openBlock() | 0xffd79d2d |
| openTime() | 0xb4256888 |
| openTrading() | 0xc9567bf9 |
| owedBnb() | 0x137225d6 |
| pair() | 0xa8aa1b31 |
| payee() | 0xae90b213 |
| pending(address) | 0x5eebea20 |
| poolSnap() | 0xe8d4fbaf |
| refineAcc() | 0x0b8ab736 |
| roundId() | 0x8cd221c9 |
| roundInfo(uint256) | 0x427f0b00 |
| router() | 0xf887ea40 |
| seed() | 0x7d94792a |
| sendFees() | 0xdff90b5b |
| settle() | 0x11da60b4 |
| state() | 0xc19d93fb |
| swapBack() | 0x6ac5eeee |
| swapBackSelf() | 0x27deaa7e |
| symbol() | 0x95d89b41 |
| totalLode() | 0xbb33c7ae |
| totalSupply() | 0x18160ddd |
| trading() | 0xec44acf2 |
| transfer(address,uint256) | 0xa9059cbb |
| transferFrom(address,address,uint256) | 0x23b872dd |
| volume() | 0xc618a1e4 |
| wbnb() | 0x8d72647e |

## Errors (generated from ABI)
Decode the first four revert bytes, including nested data/originalError. Unknown errors stop the write. Wallet code 4001 means cancellation.

| Selector | Error | Response |
|---|---|---|
| 0xdcdadd57 | BadMask() | Choose mask 1-31. |
| 0x23d9d1c6 | BadSeed() | Seed is below 0.01 BNB. |
| 0x3dade3b4 | MinterMismatch() | Deployment bindings do not match. |
| 0x969bf728 | NothingToClaim() | Re-read pending; no claimable balance. |
| 0x618104e8 | NothingToSettle() | Re-read phase; round is absent, settled, or not yet closed. |
| 0x3ee5aeb5 | ReentrancyGuardReentrantCall() | Stop; inspect the contract response and re-simulate only after resolving the cause. |
| 0x7c80a4d8 | RoundClosing() | Wait one block, then re-read and simulate. |
| 0xd313d3a2 | TooSmall() | perTile must be at least 0.0002 BNB. |
| 0x90b8ec18 | TransferFailed() | Transfer failed; stop and inspect recipient. |
| 0x1fedaaf1 | UseFunctions() | Plain BNB transfers are rejected. |
| 0x98d4901c | WrongValue() | value must equal perTile times lot count. |
| 0xd92e233d | ZeroAddress() | Stop; inspect the contract response and re-simulate only after resolving the cause. |
| 0x965f8d94 | AlreadyOpen() | Trading is already open. |
| 0xae274200 | BelowThreshold() | Commission backlog is below threshold. |
| 0xfb8f41b2 | ERC20InsufficientAllowance(address,uint256,uint256) | Stop; inspect the contract response and re-simulate only after resolving the cause. |
| 0xe450d38c | ERC20InsufficientBalance(address,uint256,uint256) | Stop; inspect the contract response and re-simulate only after resolving the cause. |
| 0xe602df05 | ERC20InvalidApprover(address) | Stop; inspect the contract response and re-simulate only after resolving the cause. |
| 0xec442f05 | ERC20InvalidReceiver(address) | Stop; inspect the contract response and re-simulate only after resolving the cause. |
| 0x96c6fd1e | ERC20InvalidSender(address) | Stop; inspect the contract response and re-simulate only after resolving the cause. |
| 0x94280d62 | ERC20InvalidSpender(address) | Stop; inspect the contract response and re-simulate only after resolving the cause. |
| 0xf8d2906c | NotMinter() | Only ROOM may mint/open trading. |
| 0x14d4a4e8 | OnlySelf() | Token internal call only. |
| 0xd85f0e84 | SwapBusy() | Conversion is in progress. |
| 0xe09f0331 | TradingNotOpen() | Trading has not opened. |
| 0x08c379a0 | Error(string) | Stop; inspect the contract response and re-simulate only after resolving the cause. |
| 0x4e487b71 | Panic(uint256) | Stop; inspect the contract response and re-simulate only after resolving the cause. |

ABI and source provenance: js/abi.js; generated by tools/generate_abi.py. Source contracts take precedence.
CharMasks is not affiliated with Binance.
