[ ETERNAL BEINGS / DIRECT CONTRACT MINT ]● MAINNET PROCEDURE
Visual Route

## One address. One epoch. One exact Secret.

Every read and write must use the same Ethereum Mainnet deployment. The address that submits Commit must also submit Reveal and Claim.

00 // VERIFY Confirm Instance

Chain ID 1. Verify deployed bytecode and the official Game address before signing.

`chainId = 1`
01 // READ Read Epoch

Read the current epoch, start block, and immutable timing constants.

`currentEpoch()`
02 // PHASE Check Commit Window

Commit only while the block offset is below `COMMIT_BLOCKS`.

`offset < 4,800`
03 // PRIVATE Generate Secret

Create one cryptographically random 32-byte value. Never use a timestamp or `Math.random()`.

`bytes32 secret`
04 // PRIVATE Save the Record

Store chain, Game, wallet, epoch, Secret, and Commitment before sending the transaction.

`DO NOT PUBLISH`
05 // WRITE Submit Commit

Hash wallet + epoch + Secret, simulate, estimate gas, then sign the Commit.

`commitMint(commitment)`
06 // WAIT Enter Reveal

Wait until the current block reaches `epochStart + COMMIT_BLOCKS`, but not the epoch end.

`4,800 ≤ offset < 7,200`
07 // WRITE Reveal Exact Secret

Use the same address, epoch, and original Secret. Verify the hash before signing.

`revealMint(epoch, secret)`
08 // WAIT Epoch Closes

Claim is available only after the epoch reaches its final block.

`offset ≥ 7,200`
09 // READ Check Draw State

Read Reveal count, claim limit, claimed count, and your claimed status.

`epochClaimLimit(epoch)`
10 // WRITE Claim Result

Simulate first. If selected and capacity remains, Claim mints the Being.

`claimMint(epoch)`
11 // VERIFY Confirm Outcome

Verify the receipt, events, ownership, token ID, Being state, and on-chain metadata.

`BeingMinted + Transfer`
PUBLIC READ / CHECK PRIVATE OFF-CHAIN DATA GAS-PAID WRITE
Commitment Formula

## The wallet address is part of the hash

commitment = keccak256( abi.encodePacked(walletAddress, epoch, secret) )

### ADDRESS

Use the exact address that will send `commitMint`. Address A cannot Reveal Address B's Commitment.

### EPOCH

Use the epoch returned immediately before Commit. A Secret committed for Epoch N cannot Reveal Epoch N+1.

### SECRET

Use exactly 32 bytes. Preserve every byte unchanged until the Reveal transaction confirms.

Never submit the raw Secret to `commitMint`. Commit accepts only the Commitment hash. Publishing the Secret before Reveal defeats the concealment step.
Direct ethers.js Example

## Generate locally, simulate, then sign

import { BrowserProvider, Contract, hexlify, randomBytes, solidityPackedKeccak256 } from "ethers"; const GAME = "0xC6D9Ea961C1E1E5F99D36970FcC824b8faA144f3"; const provider = new BrowserProvider(window.ethereum); await provider.send("eth_requestAccounts", []); const signer = await provider.getSigner(); const wallet = await signer.getAddress(); const game = new Contract(GAME, [ "function currentEpoch() view returns (uint256)", "function commitments(uint256,address) view returns (bytes32)", "function commitMint(bytes32)", "function revealMint(uint256,bytes32)", "function claimMint(uint256)" ], signer); const epoch = await game.currentEpoch(); const secret = hexlify(randomBytes(32)); const commitment = solidityPackedKeccak256( ["address", "uint256", "bytes32"], [wallet, epoch, secret] ); // Save { chainId, GAME, wallet, epoch, secret, commitment } // in protected local storage BEFORE sending Commit. await game.commitMint.staticCall(commitment); const commitReceipt = await (await game.commitMint(commitment)).wait(); // During Reveal, load the exact stored record and verify it first. const onchain = await game.commitments(epoch, wallet); const expected = solidityPackedKeccak256( ["address", "uint256", "bytes32"], [wallet, epoch, secret] ); if (onchain !== expected) throw new Error("Secret mismatch — stop"); await game.revealMint.staticCall(epoch, secret); const revealReceipt = await (await game.revealMint(epoch, secret)).wait(); // After the epoch closes, simulate Claim before sending it. await game.claimMint.staticCall(epoch); const claimReceipt = await (await game.claimMint(epoch)).wait();
Never place a private key, seed phrase, raw Secret, or decrypted keystore in website code, source control, a command line, screenshots, social posts, or agent chat. Use an injected wallet, hardware wallet, multisig, or protected local signer.
Etherscan / Manual Route

## Etherscan does not generate or remember your Secret

1. Open the verified contract and confirm the address exactly.
2. Use Read Contract to obtain `currentEpoch()`, `epochStart(epoch)`, `COMMIT_BLOCKS()`, and `EPOCH_BLOCKS()`.
3. Generate the 32-byte Secret and Commitment offline with a trusted tool.
4. Save the complete private record before connecting Etherscan.
5. Under Write Contract, connect the correct wallet and call `commitMint(commitment)`.
6. During Reveal, reconnect the same address and call `revealMint(epoch, secret)`.
7. After epoch close, call `claimMint(epoch)`. A successful Reveal does not guarantee selection when oversubscribed.

If a direct caller loses a randomly generated Secret, neither Ethereum, the contract, Etherscan, nor the official website can reconstruct it from the Commitment.
Multiple Addresses

## Each wallet follows an isolated state machine

Stored and checked per address | Why it cannot mix
--- | ---
`commitments(epoch, wallet)` | The mapping is keyed by both epoch and address.
`revealed(epoch, wallet)` | Reveal is recorded only for the caller whose Commitment matches.
`claimedEpoch(epoch, wallet)` | Claim status belongs to that address and epoch.
`hasMintedBeing(wallet)` | Each address can successfully Mint only one lifetime Being.

Address A + Epoch N + Secret A → Commitment A Address B + Epoch N + Secret B → Commitment B Commitment A ≠ Commitment B

When switching accounts, re-read all state for the newly selected address. Never reuse another address's Secret record. A Safe or other smart-contract wallet must execute Commit, Reveal, and Claim through that same contract wallet address.

Failure Prevention

## Stop before signing when any check fails

### BEFORE COMMIT

- Correct chain and Game address.
- Commit window is open.
- No existing current-epoch Commitment.
- Wallet has not already Minted.
- Secret record is safely stored.

### BEFORE REVEAL

- Reveal window is open.
- Same wallet and epoch.
- Recomputed hash equals on-chain Commitment.
- `revealed` is false.
- Simulation succeeds.

### BEFORE CLAIM

- Epoch is complete.
- Reveal succeeded.
- Claim has not already executed.
- Wallet has not already Minted.
- Simulation confirms eligibility.

Contract state is the source of truth for phase, Commitment, Reveal, Claim, supply, and ownership. The Secret is intentionally private off-chain input until Reveal.