Minting phases
Phases are time-gated by epoch ranges and resolved byget_current_phase(). Up to three sequential phases per collection.
Durations are measured in epochs, the chain’s native time unit.
MIN_PHASE_EPOCHS = 360, on the order of an hour at current epoch times. GTD and FCFS are bounded above by 259200 epochs (roughly a month). Set windows in epochs against the live chain rate rather than assuming a fixed seconds-per-epoch, since epoch wall-clock can drift. GTD and public both require a valid window; FCFS is the optional one. Phase ordering is enforced on-chain: fcfs_start >= gtd_end and pub_start >= fcfs_end.
Required here means the phase needs a valid time window. You can still make a phase mint nothing by setting its cap to
0 (closed). So a “no public sale” collection schedules a public window but leaves its cap at 0.A phase cap of
0 means the phase is closed, not unlimited. To leave a phase open to the full supply, set its cap to the max supply. The global total_minted <= max_supply guard bounds everything regardless.set_phase_override(); return to time-based resolution via clear_phase_override().
Genesis injection
Every Xcollection reserves an allocation for Xpectra holders, computed at deploy time as:genesis_mint(genesis_id) during GTD. The contract verifies the caller currently owns that Xpectra token (owner_of(genesis_id) == caller). The injection reserve is additive on top of the creator’s GTD whitelist allocation, and genesis mints share the GTD minted counter. Xpectra holders pay the GTD price (no discount).
A genesis mint is bound by every wallet limit a normal mint is: the GTD per-wallet cap and the collection’s global max_per_wallet. On top of that, each Xpectra token ID can be used only once per collection, recorded permanently, so the same NFT cannot claim multiple allocations across wallets (is_genesis_id_used, get_genesis_status).
After GTD ends, unclaimed injection slots can be released via trigger_sweep(). The sweep is permissionless once GTD has ended, so no party can withhold it.
Whitelist
Xcollection calls its bound Xlist contract to verify GTD and FCFS access at mint time. See Xlist.Payment splitting
Every mint splits payment at the contract level:
Both collect via
claim_proceeds(); balances are read with get_pending_proceeds(addr). Proceeds are never pushed alongside cross-contract calls. The pull model keeps funds isolated from AML atomicity risk.
Reveal
Collections deploy unrevealed.token_uri() returns the unrevealed_uri until reveal. The creator commits a provenance hash before mint opens, then calls reveal(base_uri) to publish the real metadata. Tokens then resolve as base_uri + token_id + .json.
On Xpectrum the base URI is the collection’s Circle (oct://<circle_id>/), so revealed metadata and art are on-chain. Reveal is irreversible. See Provenance for how the held-back metadata is verified against the pre-committed hash.
Airdrop
The owner can airdrop up to 20 tokens per transaction viaairdrop(). Airdrops bypass phase, price, and whitelist checks and count toward total_minted and max_supply.
Holder enumeration
Xcollection v3 maintains a holder index, so the platform can page through current holders on-chain viaget_holders_page(offset, limit) for distribution analytics, without scanning every token.