- No external audit has been performed yet. "Audit-grade" in this repo's description refers to engineering practice (scope, tests, documentation), not to a completed audit. Do not custody meaningful value on unaudited deployments.
- The live Nile instances are testnet deployments. The current
TDQ9k3oq…(v5) instance runs the hardened build plus the on-chain SVG renderer (TAsJa3bb…, unsealed) — standards surface, two-step handover and all three genesistokenURIs were verified on chain through public nodes right after deployment; the v5 suzerainty is currently held by aTigerTally(TMUmN6NK…) whose marshal is the deploy account, withreturnSuzeraintyas the escape hatch. v4/v3/v2/v1 are historical (see deployments/nile.md, including the honest v4 incident notes).
- 120 Hardhat specs; 100% statement / branch / function / line coverage over every deployable contract (mocks excluded), enforced by a CI gate that fails below 100%.
- Differential tests: the on-chain Base64 and decimal encoders are compared
against Node's implementations on RFC 4648 vectors plus seeded random
blobs;
escapeJsonoutput mustJSON.parseback to the original string;escapeXmlis compared against a reference implementation and every rendered SVG must pass an XML well-formedness check. - Invariant testing, dual-stack: a seeded random storm in the Hardhat suite,
plus a Foundry campaign — 64 fuzzed sequences × 128 guarded ecosystem ops
(mints, trades, gifts, time warps) under
fail_on_revertstrict mode, holding card conservation, bazaar solvency (balance == Σ proceeds), ghost-ledger accounting, no-stranded-custody, and throne stability after every single op. - Zero external Solidity dependencies — the audit surface is exactly this repository.
- Checks-effects-interactions:
safeTransferFromsettles all state before the external receiver probe; the probe is wrapped intry/catchand rejects wrong magic values.
| Power | Holder | Bound |
|---|---|---|
| mint any card / the one-shot genesis | suzerain |
genesis is single-shot for everyone, forever (genesisSealed) |
| hand over control | suzerain → heir |
two-step: heir must acceptSuzerainty(); address(0) cancels |
| swap / seal the art renderer | suzerain (until sealed) |
presentation-only: a renderer can never touch ownership, stats or metadata text; hostile output is escaped inert; failures degrade to imageless metadata; sealRenderer() is one-way |
| sign mint orders / void tallies / drive the seat while a TigerTally holds the throne | marshal (immutable per tally) |
vouchers can be bricked (voidTally) but never unsigned; every voucher mint still passes the cards contract's own validation; returnSuzerainty is the always-available escape hatch |
| administer the bazaar (fees, sweeps, freezes) | nobody | the bazaar has no owner; proceeds are withdrawable only by their seller, forever |
| pause / upgrade / burn / censor transfers | nobody | not implemented — deployed code is immutable |
Holders' transfer and approval rights follow TRC-721 exactly; the suzerain has no power over already-minted cards.
Custody recommendation: on production deployments, make the suzerain a TRON multisig account (native account-permission feature — no extra contract needed) and rehearse the two-step handover on testnet first.
extcodesizereceiver detection treats a contract under construction as an EOA — the standard, documented limitation of every ERC/TRC-721 implementation of this shape.- Plain
transferFromto a contract without a receiver hook can still strand a card (onlysafeTransferFromprobes recipients) — exactly per spec. - No enumerable extension: index via
Transfer/CardMintedevents. uncheckedblocks rely on invariants (stats ≤ 100 enforced at mint; one owner per token makes balance under/overflow unreachable); these invariants are what the test storm checks.PeachPavilion.depositGifttrusts the card contract it was constructed with; it is an escrow for this collection, not a generic vault.
Please use GitHub's private vulnerability reporting on this repository
(Security → Report a vulnerability). If that is unavailable, open an issue
titled [security] without exploit details and a maintainer will follow
up privately. Testnet-only findings are welcome too — this project treats
honest ledgers as a feature.