Sealed cards, reveal and traits
Sealed cards page revised: the pack-colourway claim now states the code (colourway follows the card's tier palette, PackSprite.tsx:16-19; PackOpen.tsx:164-167; site/tcg.js:453-464), every rule carries
A minted card is sealed. Element, design and edition are readable from the id on the day you mint. Tier and stars are not. The seed decides them, and it stays secret until the table sells out or the reveal deadline passes. Then reveal(seed) opens every card at once.
Decks, shifts and merge wait for reveal, at least until sellout or the deadline, 14 days after deploy on the testnet build.
Before this page You know what a tranche is and that mint number and token id are the same number (The mint). Constants, id ranges and addresses live on Reference.
What it is #
Sealed means half the card is public and half is committed. The sha256 hash of the secret seed is on-chain from deploy, before the first table mint, and reveal is the one call that hands the seed over. Ids go out in order and traits are deterministic, so a seed known mid-mint would let anyone compute which unminted ids land Tier 9 and buy those. The deadline keeps reveal from deadlocking if the table never sells out. The reason for the wait is sniping, not theatre.
Rules #
- SEED_COMMITMENT is the sha256 hash of the seed string, set in the constructor and never rewritten; the production seed is a 256-bit value kept off-chain (contracts/src/MinersNFT.sol:70-71,135; deploy/mainnet-config.md:30-33).
reveal(seed)is open to anyone who knows the seed, once, elseAlreadyRevealed(MinersNFT.sol:271-272).- It runs only after all 5,040 table cards are minted or after REVEAL_DEADLINE, else
RevealTooEarly(MinersNFT.sol:277-279). - A seed whose hash does not match reverts
BadSeed(MinersNFT.sol:280). - After reveal the seed is public through
revealedSeed()(MinersNFT.sol:294-296). - Until reveal,
cardTraits(tokenId)andmergeCards(keepId, burnId)revertNotRevealedandbindDeck(cardIds)revertsNotRevealedYet(MinersNFT.sol:306,319; contracts/src/MinePool.sol:215). - The mint has no end time and does not stop at reveal (MinersNFT.sol:192-194).
- Stars move only through merge, +1 capped at 6 (MinersNFT.sol:336-338).
Numbers #
deploy SEED_COMMITMENT on-chain; ids 5,041 to 5,050 minted to TREASURY MinersNFT.sol:135,140-144
mint window cards sealed; cardTraits and mergeCards revert NotRevealed MinersNFT.sol:306,319
bindDeck reverts NotRevealedYet MinePool.sol:215
gate 5,040 minted OR block time >= REVEAL_DEADLINE, else RevealTooEarly MinersNFT.sol:277-279
reveal(seed) sha256(seed) == SEED_COMMITMENT, else BadSeed; once, else MinersNFT.sol:271-285
AlreadyRevealed; emits BatchMetadataUpdate(1, 5050)
after traits, decks, shifts and merge live; the mint stays open MinersNFT.sol:192-194
Every element owns 252 consecutive ids and the four editions of one design sit side by side, so element, design and edition are arithmetic on the id (contracts/src/CardTraits.sol:72-78). The odd part is that the star floor is public while the stars are not.
| Trait | Before reveal | After reveal | Source |
|---|---|---|---|
| Element | From the id, (id - 1) / 252 | Same | CardTraits.sol:25,72-73 |
| Design | From the id, ((id - 1) % 252) / 4 | Same | CardTraits.sol:74 |
| Edition | From the id, (id - 1) % 4 | Same | CardTraits.sol:75 |
| Star floor | Equal to the edition | Same | CardTraits.sol:31-32,122 |
| Tier | Sealed | Seed shuffle per element, 1 to 9 | CardTraits.sol:79,89-109 |
| Exact stars | Sealed, floor to floor + 3 | edition + hash % 4 | CardTraits.sol:80,113-123 |
The tier census is fixed. Every element has 14 Tier 1 designs and one Tier 9 design; the seed only decides which design is which.
| Tier | Designs per element | Cards per element (derived, x4 editions) | Cards table-wide (derived, x20 elements) | Share of table (derived) | Base weight | Source |
|---|---|---|---|---|---|---|
| T1 | 14 | 56 | 1,120 | 22.2% | 1 | CardTraits.sol:36; MinePool.sol:247 |
| T2 | 11 | 44 | 880 | 17.5% | 2 | CardTraits.sol:36; MinePool.sol:247 |
| T3 | 9 | 36 | 720 | 14.3% | 4 | CardTraits.sol:36; MinePool.sol:247 |
| T4 | 8 | 32 | 640 | 12.7% | 8 | CardTraits.sol:36; MinePool.sol:247 |
| T5 | 7 | 28 | 560 | 11.1% | 16 | CardTraits.sol:36; MinePool.sol:247 |
| T6 | 6 | 24 | 480 | 9.5% | 32 | CardTraits.sol:36; MinePool.sol:247 |
| T7 | 4 | 16 | 320 | 6.3% | 64 | CardTraits.sol:36; MinePool.sol:247 |
| T8 | 3 | 12 | 240 | 4.8% | 128 | CardTraits.sol:36; MinePool.sol:247 |
| T9 | 1 | 4 | 80 | 1.6% | 256 | CardTraits.sol:36; MinePool.sol:247 |
| One-of-one (T9) | 1 | 1 | 10 | outside the table | 256 | CardTraits.sol:30,66-70 |
The ten one-of-ones are design 63 of elements 0 to 9 and sit outside the 5,040.
Edition e draws stars uniformly from e to e + 3, so a 6-star card straight from the mint exists only in edition 3.
| Edition | Min stars | Max stars | 6 stars at mint | Source |
|---|---|---|---|---|
| 0 | 0 | 3 | No | CardTraits.sol:32,122 |
| 1 | 1 | 4 | No | CardTraits.sol:32,122 |
| 2 | 2 | 5 | No | CardTraits.sol:32,122 |
| 3 | 3 | 6 | Yes, 1 in 4; expected 315 cards (derived, 1,260 x 1/4) | CardTraits.sol:32,122 |
The element order is permanent because the names feed the hash. Index 0 to 19 runs Void, Thunder, Moon, Sun, Bleeding, Defense, Heal, Cloud, Attack, Earth, Sound, Water, Soul, Fire, Plant, Poison, Demon, Light, Charm, Slime. Id ranges and one-of-one ids are in Table 10.4.
Packs come in 20 designs, one per element, each in 9 colourways (site/tcg.js:430-433,446-451). The colourway the app shows follows the card's tier palette, brown for Tier 1 to yellow for Tier 9 (app/web/src/components/PackSprite.tsx:16-19; app/web/src/components/PackOpen.tsx:164-167; site/tcg.js:453-464). Packs exist only in the app's opening animation.
| Step | Formula | Source |
|---|---|---|
| Hash | First 8 bytes of sha256 over ':'-joined strings, read as a big-endian uint64 | CardTraits.sol:173-178; app/api/seed/generate.py:58-66 |
| Shuffle | Per element, Fisher-Yates over designs 0 to 62; step i swaps with j = hash(seed:element:fy:i) % (i + 1) | CardTraits.sol:156-171 |
| Tier | Shuffled positions 0 to 13 are T1, the next 11 T2, then 9, 8, 7, 6, 4, 3, and the last position T9 | CardTraits.sol:36,89-109; generate.py:44-45,69-92 |
| Stars | edition + hash(seed:element:design:edition) % 4 | CardTraits.sol:113-123 |
| Merge overlay | A merged card's stored tier and stars replace the seed values; element, design and edition never change | MinersNFT.sol:351-364 |
| Parity | Solidity and Python are locked against test/vectors/traits.json | CardTraits.sol:7-11 |
| State | URI | Name and attributes | Source |
|---|---|---|---|
| Sealed | tokenURI(tokenId) is {baseURI}/hidden.json | TCG Miners - Sealed | MinersNFT.sol:371-374; app/api/routes/meta.py:56-62 |
| Revealed | tokenURI(tokenId) is {baseURI}/{id}.json | TCG Miners #{id} - {Element} Card; Element, Tier, Stars, Star Class (0-2, 3, 4, 5, 6), Weight Class (Common to Mythic), Weight (number), Edition, 1 of 1, Design. Tier, Stars and the two classes are strings so OpenSea rarity counts them; the classes are ordinal buckets that make rank rise with stars and weight | MinersNFT.sol:375; meta.py:84-130 |
| Collection, either state | contractURI() is {baseURI}/contract.json (ERC-7572) | MinersNFT.sol:383-386 |
The image is keyed by element and tier, so a merge changes the picture (meta.py:65-72). The contract advertises interface 0x49064906 (MinersNFT.sol:452).
Worked example #
Id 1 is Void, design 0, edition 0. Id 3,277 is the Fire card of worked example D. Take z = id - 1 and divide.
z = 3,277 - 1 = 3,276
element = 3,276 / 252 = 13, remainder 0 -> Fire, ids 3,277 to 3,528 CardTraits.sol:73,143
design = 0 / 4 = 0 CardTraits.sol:74
edition = 3,276 % 4 = 0 CardTraits.sol:75
star floor = 0, so 0 to 3 stars at mint CardTraits.sol:122
tier = sealed until reveal(seed) CardTraits.sol:79
Id 3,301 sits 24 ids on, so design 24 / 4 = 6, edition 0, floor 0. After reveal both come up Tier 2, with 1 and 3 stars, and that pair is merged on Merge. Before reveal cardTraits(3277) reverts NotRevealed (MinersNFT.sol:306; CardTraits.sol:72-78).
Edge cases #
- Ids 5,041 to 5,050 are the ten one-of-ones, minted to TREASURY in the constructor (MinersNFT.sol:140-144). They never merge, else
UniqueNotMergeable(MinersNFT.sol:328-329), and carry mining weight but no cost weight (MinePool.sol:249). Distribution is to be announced. - REVEAL_DEADLINE is 14 days after deploy on the testnet build (contracts/script/Deploy.s.sol:103); the mainnet value is set at deploy.
- Marketplaces show the sealed name until reveal. Reveal emits
BatchMetadataUpdate(1, 5050)(MinersNFT.sol:285); a marketplace that ignores it keeps the old name until you refresh the item.
Verify it on-chain #
Verify it on-chain On the MinersNFT read-contract tab (Robinhood testnet 46630, deploy/testnet-addresses.md:3,13; all addresses) call
SEED_COMMITMENT(),REVEAL_DEADLINE(),revealed(),revealedSeed(),totalMinted(),cardTraits(3277),tokenURI(3277)andcontractURI()(MinersNFT.sol:70-76,258-261,289-309,371-386). After reveal, sha256 ofrevealedSeed()equalsSEED_COMMITMENT()(MinersNFT.sol:280) andcardTraits(3277)returns element 13, design 0, edition 0 (CardTraits.sol:72-78).
Not in the game #
Not in the game "Each tier earns 3x the one below" (opensea-description.txt:5,19). 2x; base weight is 2^(tier-1) (MinePool.sol:247), matrix on Decks. "Stars are upgrades earned after minting" (site/index.html:298). Assigned at mint by the seed; merge adds one, capped at 6 (CardTraits.sol:113-123; MinersNFT.sol:336-338). "18 pack designs" (opensea-description.txt:3,19). 20, one per element; the 18 came from an incomplete sprite sheet (site/tcg.js:438-451).
Next #
Read this if you are here to... Top up a bond, read the bond rule. Claim, read Claiming. Merge two of a kind, read Merge. Sell a card, read Locked; a card in a deck cannot move.
Next page, Decks and weight, where revealed cards become one deck with one weight.