mirror of
https://github.com/luxfi/tokenomics.git
synced 2026-10-30 15:15:35 +00:00
Ethereum Media 0x31e0F919 probed live at block 25612642: 50 tokens, ids 1-50 contiguous, zero duplicates, zero malformed/truncated tokenURIs, all 50 with a non-zero content hash. The "~43 interrupted URIs" in the task backlog does not exist on chain and has no counterpart in the broadcast record. The only Ethereum defect is that every tokenURI names lux.town, which has no nameservers — and that CANNOT be fixed on chain: the deployed Zora-fork Media has no setTokenURI, no setBaseURI and no owner override, only updateTokenURI gated onlyApprovedOrOwner. The repair is the client-side host rewrite to cdn.lux.network, already live. The 9 treasury duplicates were real, and the deployed fix was only half applied. MintTreasuryValidators minted a naive consecutive #33-#100 instead of the 68-serial complement; nine collided; FixTreasuryNumbers renumbered them but templated all nine payloads off validator #33 and edited only `name`. Every one kept "Validator No": 33 and artwork reading "VALIDATOR #33 / 100", so the pre-reset collection had TEN tokens rendering as #33. The existing verification passed because it only ever read `name`. Root cause: the serial was materialised 127 times as ~450 KB of literal base64 across three Solidity scripts. Fix: one registry holds each serial once, one renderer derives the metadata. data/eth-genesis-inventory.json live Ethereum state (generated, re-checkable) data/genesis-registry.json canonical 118 rows: 100 validators #1-#100 + 18 coins scripts/probe-eth-genesis.mjs eth_call/eth_getCode only, cannot send a tx scripts/gen-genesis-registry.mjs invariants: serials {1..100}, treasury set = {1..100} \ ETH validators, bonds match the ETH tokenURI, totalLuxLocked 102,583,000,000 scripts/genesis-metadata.mjs the ONE renderer (one SVG template) scripts/verify-genesis-metadata.mjs 118/118 deployed payloads reproduced byte-for-byte; the 9 defective ones pinned as a regression test scripts/gen-remint-plan.mjs un-executed re-mint plan; mints each treasury validator AT its canonical serial, so no renumber step exists to get half-applied No transaction is sent by anything in this repo. C-Chain 0x004287C4 confirmed wiped (eth_getCode = 0x) — the re-mint remains owner-gated and deferred.
70 lines
4.3 KiB
JavaScript
70 lines
4.3 KiB
JavaScript
// Generate data/genesis-remint-plan.json — the complete, un-executed re-mint
|
|
// plan for the Genesis collection on Lux C-Chain 96369.
|
|
//
|
|
// Context: contract 0x004287C4… was WIPED by the 2026-07-10 fresh genesis
|
|
// (eth_getCode returns 0x). Re-establishing the collection means redeploying
|
|
// GenesisNFTs and minting all 118 tokens. This file is the exact argument list
|
|
// for that mint, derived from the canonical registry and the ONE renderer — it
|
|
// replaces the three hand-materialised Solidity scripts whose naive #33..#100
|
|
// numbering caused the nine-way collision in the first place.
|
|
//
|
|
// NOTHING HERE IS BROADCAST. The plan is data for owner review.
|
|
import { readFileSync, writeFileSync } from 'node:fs'
|
|
import { tokenURI } from './genesis-metadata.mjs'
|
|
|
|
const reg = JSON.parse(readFileSync(new URL('../data/genesis-registry.json', import.meta.url), 'utf8'))
|
|
|
|
// GenesisNFTs.sol: enum NFTType { VALIDATOR, CARD, COIN } / enum Tier { GENESIS, VALIDATOR, MINI, NANO }
|
|
const NFT_TYPE = { VALIDATOR: 0, CARD: 1, COIN: 2 }
|
|
const TIER = { GENESIS: 0, VALIDATOR: 1, MINI: 2, NANO: 3 }
|
|
const SPEC = {
|
|
'GENESIS VALIDATOR': { nftType: NFT_TYPE.VALIDATOR, tier: TIER.GENESIS },
|
|
'GENESIS COIN': { nftType: NFT_TYPE.COIN, tier: TIER.GENESIS },
|
|
'VALIDATOR COIN': { nftType: NFT_TYPE.COIN, tier: TIER.VALIDATOR },
|
|
'MINI COIN': { nftType: NFT_TYPE.COIN, tier: TIER.MINI },
|
|
'NANO COIN': { nftType: NFT_TYPE.COIN, tier: TIER.NANO },
|
|
}
|
|
|
|
// Mint order == final C-Chain tokenId. Ethereum-origin tokens keep ids 0..49 so
|
|
// `originTokenId` stays id+1, exactly as the 2026-07-07 migration recorded it;
|
|
// treasury validators follow at 50..117. Unlike the original run, each treasury
|
|
// token is minted AT ITS CANONICAL SERIAL — there is no collide-then-renumber
|
|
// step, so the nine-way duplicate cannot recur.
|
|
const order = [...reg.tokens].sort((a, b) => a.cchainId - b.cchainId)
|
|
|
|
const mints = order.map((row) => {
|
|
const spec = SPEC[row.tier]
|
|
if (!spec) throw new Error(`no mint spec for tier ${row.tier}`)
|
|
return {
|
|
cchainId: row.cchainId, serial: row.serial, name: row.name, tier: row.tier,
|
|
to: row.owner, nftType: spec.nftType, tierEnum: spec.tier,
|
|
originTokenId: row.ethTokenId, bond: row.bond,
|
|
media: { tokenURI: tokenURI(row), contentURI: 'onchain', metadataURI: '', contentHash: `0x${'0'.repeat(64)}`, metadataHash: `0x${'0'.repeat(64)}` },
|
|
}
|
|
})
|
|
|
|
// The plan must reproduce the registry's totals exactly, or it is not the plan.
|
|
const fail = []
|
|
if (mints.length !== reg.totals.tokens) fail.push(`mints=${mints.length} want ${reg.totals.tokens}`)
|
|
mints.forEach((m, i) => { if (m.cchainId !== i) fail.push(`mint ${i} has cchainId ${m.cchainId} — order must equal tokenId`) })
|
|
const bonded = mints.reduce((a, m) => a + m.bond, 0)
|
|
if (bonded !== reg.totals.totalLuxLocked) fail.push(`bond total ${bonded} want ${reg.totals.totalLuxLocked}`)
|
|
const vSerials = mints.filter((m) => m.nftType === NFT_TYPE.VALIDATOR).map((m) => m.serial).sort((a, b) => a - b)
|
|
vSerials.forEach((s, i) => { if (s !== i + 1) fail.push(`validator serial ${s} at position ${i + 1}`) })
|
|
// Every treasury mint must already carry its canonical serial — no renumber step.
|
|
for (const m of mints) if (m.originTokenId === null && m.serial !== order.find((r) => r.cchainId === m.cchainId).serial) fail.push(`treasury ${m.cchainId} serial drift`)
|
|
if (fail.length) { console.error('REMINT PLAN INVALID:\n ' + fail.join('\n ')); process.exit(1) }
|
|
|
|
writeFileSync(new URL('../data/genesis-remint-plan.json', import.meta.url), JSON.stringify({
|
|
$comment: 'UN-EXECUTED re-mint plan for Lux C-Chain 96369 GenesisNFTs. Generated by scripts/gen-remint-plan.mjs. No transaction is sent by any script in this repo.',
|
|
chainId: 96369, contract: 'redeploy required — 0x004287C47efc912FEc391979154454a8017A76C6 has no code',
|
|
abi: 'mintToken(address to, MediaData data, NFTType nftType, Tier tier, string name)',
|
|
totals: { mints: mints.length, validators: vSerials.length, coins: mints.length - vSerials.length, totalLuxLocked: bonded },
|
|
mints,
|
|
}, null, 2) + '\n')
|
|
|
|
console.log(`OK ${mints.length} mints planned, tokenIds 0..${mints.length - 1}`)
|
|
console.log(`OK validators #${vSerials[0]}..#${vSerials.at(-1)} minted at canonical serials — no renumber step`)
|
|
console.log(`OK totalLuxLocked ${bonded.toLocaleString('en-US')} LUX matches the registry`)
|
|
console.log(` NOTHING BROADCAST — plan only.`)
|