Loading
PRICE DISCUSSION DOCS
APP
Updated 2026-10-12·View as Markdown

Contracts — PDKeychains

The Le Depanneur's capsule machine on-chain: an ERC-721 where every Keychain is a one-of-one generative charm, drawn entirely at read time by a renderer contract — no stored images, no external anything. In the app's test phase the machine runs on sim-ETH; this contract is the same machine for real ETH, and deploys with the platform's launch wave.

The crank

function crank(uint8 coin, uint32 streak, uint8 rank, uint256 deadline, bytes calldata sig)
    external payable returns (uint256 tokenId);

Insert coin, crank, a random charm drops — one per crank, that's the ritual. The two coin slots (0 YIN · 1 YANG) steer palette, face, and accessory weights; shapes are universal, so the rarest chase is equal on either slot. The crank commits the charm to its own block and reveal records the seed from the next block on — the same commit-reveal as PDProject — so no wallet or contract can see a roll and revert it. Anyone may reveal (PD's server does, within seconds); until then the charm shows a placeholder, and MetadataUpdate (ERC-4906) tells marketplaces when the art arrives. Payment is exact (priceWei + revealFeeWei) and force-sent inside the transaction — of the price, platform 5% (wallet read live from the factory) and the remainder to the shop; the reveal fee on top goes whole to the factory's storage-fee wallet, the wallet that sends the reveal and pays its gas — so a payee that refuses ETH still gets it and can never stop a crank, and no ETH ever rests here. Two wallets fixed in the contract (FREE_CRANKER_A and FREE_CRANKER_B) crank FREE_CRANKS (100) times each for the reveal fee alone, with no price; no admin can add, remove or refill them, and freeCranksLeft(address) reads what each has left.

THE ART BELONGS TO THE CHARM, NOT THE KEEPER. Color, finish, and chain metal all roll per charm off its own seed on a common→rare ladder — gold and chrome are genuine rare pulls. What the keeper's PD life buys is LUCK: sig is the app's attestation of the cranker's live PriceStreak and PriceRank, signed by the factory's dedicated attestation key (its own key, deliberately not the settlement key — two unrelated jobs never share one secret); the machine derives an odds tier (0–3) from it on-chain and freezes it into the charm forever — it shows as the charm's Luck trait, the charm's provenance. The attestation's deadline may sit at most fifteen minutes out — it carries no nonce by design, so its short life is what stops one signature becoming a permanent luck pass. Luck only widens the rare end of the rolls — it never repaints a charm afterwards. An empty sig cranks unattested at luck 0, the floor odds, so the machine keeps turning even if the signer is down — and that can't be gamed, because the floor is the worst tier there is.

The living layer

  • Polish — polish(...) syncs the keeper's attested PriceStreak/PriceRank onto the charm's traits (EIP-712 signature, per-charm nonce, keeper-bound, deadline at most fifteen minutes out — so an unused polish can't be held back and played after the streak behind it is gone). It records their life; it cannot change the art, by design — the suite proves a maximum-life polish leaves the artwork byte-identical.
  • The bond — every hand-to-hand transfer wipes the polish: a keeper's life is not a purchasable state. The charm's own identity — seed, coin, luck, and christened name — survives forever, so a sold charm looks exactly as it always did. Christening, polishing and the wipe each emit MetadataUpdate, so marketplaces refresh the name tag and traits.
  • Christen — name your charm once, ever, engraved on its tag and carried as its Name trait (the token itself stays Price Discussion Keychain #<tokenId>). 2–12 characters, A–Z 0–9 and one space between words (never leading, trailing or doubled), charset-guarded on-chain so a name can never break the metadata and the tag engraves exactly the stored name.

The art, on-chain

tokenURI and charmSVG draw the complete charm — shape, googly face, rubber-hose arms, chain, finish, accessories, the swing and the blink — as a self-contained SVG assembled by PDKeychainRenderer with three part stores beside it (shapes · faces · trait names), split only for the EVM's contract-size limit and referenced immutably: the four contracts are one artist. The attributes lead with the charm's Element (six elements, two shapes each), then coin, luck, shape, palette, material, eyes, and the rest, plus the keeper's attested PriceStreak and PriceRank.

The renderer address is swappable by the shop admin during an art-bugfix window; a swap emits BatchMetadataUpdate (ERC-4906) over every charm minted so far, so marketplaces redraw them. Then lockRenderer() freezes the art forever — one way, no reopening. The collection is Price Discussion Keychains (the ERC-721 name(), and the name contractURI() serves with its description as on-chain JSON for marketplaces); every charm is Price Discussion Keychain #<tokenId>.

Royalties and admin

5% secondary royalty (ERC-2981) to royaltyReceiver, fixed at deploy: the sticker shop's solo StickerSplitter vault, which splits it 3% to the sticker shop's admin and 2% to the factory's live platform wallet. Admin holds price and on/off dials, the reveal fee (only inside a floor/ceiling corridor fixed at deploy), plus the renderer window, transfers two-step, and can never touch a minted charm's seed, luck, name, or traits. A dust-rescue sweep exists for ether force-sent to the contract — cranks push everything out in-flight and there is no other way for ETH to land here, so the sweep can only ever recover dust, never touch the machine's money.

Further reading