Skip to content

Redchar1992/ThreeRealmsCards

Repository files navigation

Three Realms Cards · 三分天下

CI License: MIT Solidity Coverage

A fully on-chain, modular TRC-721 on TRON, engineered to audit-grade practice — and a complete, brutally honest dogfooding case study of TronIDE.

English · 简体中文

Three Kingdoms general cards: four factions (WEI / SHU / WU / QUN), five rarities (N → LEGEND), four 0–100 stats, and a one-shot "Peach Garden" genesis — Liu Bei, Guan Yu, Zhang Fei as LEGEND 1/1s, sealed forever after one mint. Metadata — and, through the sealable SVG renderer, the card art itself — lives entirely on chain as data URIs: no IPFS pin to lapse, no metadata server to die. If the chain is up, the cards are whole.

Why this repo is worth reading

  • A reference TRC-721, zero dependencies. The full core + metadata surface — both safeTransferFrom overloads with a try/catch receiver probe, TRC-165 with compiler-computed type(X).interfaceId (no hand-copied magic constants), spec-grade revert semantics on ownerOf / balanceOf / getApproved, two-step ownership handover, custom errors throughout. No OpenZeppelin import: every byte that ends up on chain is in this repo, which makes the whole surface auditable in one sitting.
  • Fully on-chain metadata and artwork. Card → JSON → Base64 → data: URI for metadata, plus CardRenderer — the card face drawn as pure SVG in Solidity (faction-themed frame, rarity stars, stat bars) and embedded as a nested data:image/svg+xml;base64 URI. User strings are JSON-escaped and XML-escaped on chain; a broken or hostile renderer degrades to imageless metadata instead of bricking tokenURI; the suzerain can sealRenderer() forever once the art is final.
  • Deliberately spiky Solidity. File-level types and free functions, a global using-for, aliased named imports, a same-file-two-paths import trap, a public-state-var overriding an interface function, unchecked blocks, an assembly guard, reverting receive/fallback — each one placed on purpose to stress compilers, flatteners, UML generators, linters and analyzers, and annotated with why. See docs/architecture.md.
  • Signature-driven lazy minting (虎符 TigerTally). A tally contract takes the suzerainty — the two-step handover exists precisely so a contract can hold the throne safely — and redeems EIP-712 MintOrders: nested-struct hashing (the order wraps a full Card), bearer and bound-with-relayer voucher modes, voidable nonces, malleability-guarded ecrecover, and a marshal-gated passthrough for every suzerain power including the escape hatch back. The on-chain digest is differentially anchored to ethers' TypedDataEncoder in tests.
  • Real value handled the boring way (市集 CardBazaar). A fixed-price, TRX-settled stall market with escrowed listings and pull-payment proceeds — paying sellers inline would let any seller with a reverting receive() brick their own listing's purchase. withdraw() is checks-effects-interactions, proven by a hostile seller that attempts a reentrant drain mid-payout and finds an already-zeroed ledger. No owner, no fees, no sweep: the bazaar's admin column in the trust model reads nobody.
  • A dual verification stack, gated in CI. Hardhat: 120 specs at 100% statement/branch/function/line coverage, with differential tests of every on-chain codec (Base64, decimal, JSON/XML escapes, the EIP-712 digest) against reference implementations. Foundry: a stateful invariant campaign — 64 fuzzed sequences × 128 guarded ecosystem ops (mints, trades, gifts, time warps) under fail_on_revert strict mode — proving card conservation, bazaar solvency, ledger accounting, and that custody contracts can never strand a card across every reachable sequence. The forge harness shim (ForgeLite) is written in-repo: zero external dependencies extends to the test base itself.
  • A real dogfooding campaign, honestly kept. The entire project — scaffold, edit, lint, compile, VM deploy, debug, record/replay, TronBox export, git push, TronLink mainnet-style deploys, flatten & verification — was executed inside TronIDE, driving 23 IDE features and filing 13 findings, of which 6 were fixed upstream with regression gates and 3 were retracted after strict re-verification (the ledger counts our own misreads too). See docs/case-study.md.

Audit status: engineered to audit-grade practice, not yet externally audited. Read SECURITY.md before depositing value you care about.

Contracts

contracts/
├── ThreeRealmsCards.sol        the TRC-721 card contract
│   ├── interfaces/
│   │   ├── ITRC165.sol         interface detection
│   │   ├── ITRC721.sol         core surface (is ITRC165) — 9 fns XOR to 0x80ac58cd
│   │   ├── ITRC721Metadata.sol name / symbol / tokenURI (is ITRC721)
│   │   ├── ITRC721Receiver.sol safe-transfer hook
│   │   └── IRenderer.sol       pluggable art hook (Card in, image URI out)
│   ├── access/Suzerain.sol     two-step Ownable (主公): designate heir → heir accepts
│   ├── render/CardRenderer.sol 丹青 — the card face as pure on-chain SVG
│   ├── types/CardTypes.sol     file-level enums, Card struct, free fns, global using-for
│   ├── libs/CardCodec.sol      Card → data:application/json;base64 (JSON-escaped)
│   ├── libs/Base64.sol         assembly encoder (public-node CPU caps forced it — see docs)
│   └── utils/StrUtils.sol      toString / equal / escapeJson / escapeXml
├── PeachPavilion.sol           gift escrow with claim windows: the heir claims until
│                               the deadline (boundary inclusive), the giver reclaims after
├── TigerTally.sol              虎符 — EIP-712 signed mint orders (lazy minting);
│                               holds the suzerainty while in service
├── CardBazaar.sol              市集 — fixed-price stalls, TRX-settled, escrowed
│                               listings, pull-payment proceeds; no owner, no fees
└── mocks/TestMocks.sol         test doubles only — never deploy

Live on Nile testnet

Version Contract Address Notes
v5 (current) ThreeRealmsCards + CardRenderer + TigerTally + CardBazaar + PeachPavilion TDQ9k3oqaV1tErua4uft1ZnndV96oFBH4X · TAsJa3bb… · TMUmN6NK… · TKfYhL4A… on-chain SVG art live; the tally holds the suzerainty (Zhuge Liang #4 minted via EIP-712 voucher); the bazaar closed a full list → buy → withdraw cycle with real TRX; the pavilion (TTSyQWDj…) proved its claim/regret windows in real chain time
v4 (historical) first renderer deploy THRSFpEV… renderer accidentally sealed by a driver bug; 4.07M-gas tokenURI refused by public nodes (OutOfTimeException) — both documented
v3 (historical) hardened, 11 files TYK5P6bU… supportsInterface + two-step ownership verified on chain
v2 (historical) modular, 9 files TEzyMokX… cardKeyOf (global using-for) verified on chain
v1 (historical) single file TBig1iST… first campaign deploy

Transactions, deployer, energy numbers, the honest incident notes and verification materials: deployments/nile.md.

Quickstart

npm install
npm test              # 120 specs, ~3s, no local TRON node needed
npm run coverage      # istanbul report; CI enforces 100%
forge test            # invariant campaign: 64×128 guarded ops, 5 invariants
npx hardhat compile   # solc 0.8.20, evm target paris (no PUSH0 ahead of the TVM)

The Hardhat suite is a logic-regression harness: upstream solc + an EVM is instruction-equivalent to the TVM for everything this codebase uses, so unit tests run anywhere, fast. On-chain integration (energy model, TronLink signing, TronScan verification) is exercised separately through the TronIDE scenario replays (scenarios/) and the TronBox export (exports/tronbox/).

Repository layout

Path What it is
contracts/ the production sources (see map above)
test/ Hardhat suite — conformance, receiver matrix, differentials, invariants
docs/architecture.md module walkthrough + the annotated "spiky constructs" inventory
docs/case-study.md the TronIDE dogfooding campaign, in English
docs/journal.md full campaign journal (Chinese, primary source)
docs/dogfooding-matrix.md 23-feature coverage matrix
deployments/nile.md live addresses, txids, compiler settings
scenarios/ IDE recorder scenario (deploy → genesis → reads), replayable
exports/ IDE-generated TronBox project + flattened verification sources
tools/ Playwright scripts that drove the IDE for each campaign phase

The dogfooding story, in numbers

23 IDE features exercised end-to-end · 13 findings filed (J-001…J-013) · 6 fixed upstream with regression gates · 3 honestly retracted after re-verification · 2 root-caused to a shared LocalStorage-backend design and scheduled as upstream migration work · 2 live deployments signed through TronLink on Nile.

The campaign's discipline — verify strictly before concluding, retract in public, prefer reading the chain over reading the UI — is documented in docs/case-study.md.

License

MIT

About

Audit-grade, fully on-chain, modular TRC-721 on TRON — built end-to-end inside TronIDE as a complete dogfooding case study (23 features, 13 findings, 2 Nile deploys)

Topics

Resources

License

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors