Marketplace for sealed AI prompts on 0G. Each prompt is an ERC-7857 iNFT whose key re-encrypts to the buyer on purchase — the seller cryptographically loses access.
0gPrompt is a marketplace for sealed AI prompts on 0G. Every prompt is an ERC-7857 iNFT whose AES-256-GCM encryption key re-seals to the buyer on every purchase, and the seller's old key cryptographically
stops working the moment the transaction confirms.
The problem: a system prompt or agent config has real value and zero defensibility. Screenshots leak instantly. PromptBase resells text you can copy on sight. Custom GPTs lock you to one vendor. There has
never been a way to transfer the access to an opaque artifact atomically, with provable loss-of-access for the seller — until ERC-7857.
How a purchase works end-to-end:
- The buyer clicks Buy on /market (flat 0.1 OG, no haggling)
- Their browser pulls the ciphertext from 0G Storage, decrypts it with the seller's escrowed key, generates a fresh AES-256 key bound to the buyer, re-encrypts the manifest, and uploads the new ciphertext
(tx 1)
- The browser then calls purchase(tokenId, sealedKey, proof) with value: 0.1 OG (tx 2). The contract verifies the oracle proof, rebinds the iNFT to the new ciphertext root + metadata hash, transfers
ownership, forwards 0.1 OG to the seller, and emits SealedKeyDelivered(tokenId, buyer, sealedKey)
- The buyer's wallet auto-scans SealedKeyDelivered events and stores the delivered key locally so Reveal works in /prompts immediately. No manual import step
What owning a prompt iNFT actually gives you:
- Decrypt anywhere. The plaintext lives only on your machine after Reveal. Copy it into ChatGPT, Claude, a local Llama, an internal pipeline — no vendor lock-in, no API the platform can pull.
- Rent without selling. authorizeUsage(executor, permissions) grants a scoped grant (e.g. use:10, day:30) to another address. Revoke it in one tx; the renter never holds the key.
- Resell or escrow. Because access is the token, you can flip a prompt, list it in a fund, or transfer it as part of a larger asset bundle. The next buyer gets a fresh re-sealed key; you lose access on
confirm.
- Atomic accountability. Every sale, rent, and revoke is an on-chain event. No platform can rewrite the access log; no seller can "still have a copy" — the contract enforces the loss.
- Cloneable derivatives. clone() lets the owner mint a re-sealed copy of a prompt (for an agent template fleet, for example) without giving up the original.
Why 0G specifically: the full stack lives on one network. 0G Chain runs the iNFT, 0G Storage holds the encrypted prompt bodies (Merkle root referenced on chain as encryptedURI), and the oracle verifies
the re-encryption proof. One wallet, one chain, one set of fees — no bridging between an L1, a separate storage network, and a third-party oracle.
<p>Everything was built from scratch during the hackathon — no pre-existing codebase.</p><p></p><p> <strong>Smart contracts</strong> — Wrote <code data-inline="true" spellcheck="false">ERC7857.sol</code> implementing the full sealed-key surface <code data-inline="true" spellcheck="false">mint</code>, <code data-inline="true" spellcheck="false">transfer</code>, <code data-inline="true" spellcheck="false">purchase</code>, <code data-inline="true" spellcheck="false">clone</code>, <code data-inline="true" spellcheck="false">authorizeUsage</code>, <code data-inline="true" spellcheck="false">revokeUsage</code>) + <code data-inline="true" spellcheck="false">MockOracle.sol</code> as the testnet verifier. 13</p><p> Hardhat tests passing. Caught and patched a real auth bug mid-build (proof-replay theft via <code data-inline="true" spellcheck="false">transfer()</code>), added a payable <code data-inline="true" spellcheck="false">purchase(tokenId, sealedKey, proof)</code> for one-click buy with 0.1 OG forwarded to</p><p> the seller, and iterated through 4 deployments on 0G Galileo. Final: iNFT <code data-inline="true" spellcheck="false">0x29dd28Ee28f7876a01bA75a784835376951Bdb6C</code>, oracle <code data-inline="true" spellcheck="false">0xd10ebe48df3F8D7354B9C6d66535944910e1EA49</code>.</p><p> </p><p> <strong>0G integrations</strong> — Wrapped the 0G Storage TS SDK for encrypted blob upload/download <code data-inline="true" spellcheck="false">ogStorage.ts</code>), built a viem→ethers signer bridge so the SDK works with the wagmi wallet <code data-inline="true" spellcheck="false">signer.ts</code>), and</p><p> implemented AES-256-GCM via Web Crypto in a layout that round-trips between browser and Node <code data-inline="true" spellcheck="false">crypto.ts</code>).</p><p></p><p> <strong>Sealed-key pipeline</strong> — <code data-inline="true" spellcheck="false">reseal.ts</code> is the shared download → decrypt → re-encrypt → upload module used by both seller-side <code data-inline="true" spellcheck="false">transfer()</code> and buyer-side <code data-inline="true" spellcheck="false">purchase()</code>. Every ownership change re-encrypts the</p><p> prompt under a fresh key bound to the new owner; the previous owner's key still exists locally but decrypts nothing the contract points at. This is what makes the seal mean something.</p><p></p><p> <strong>Frontend (Next.js 16, RainbowKit + wagmi + viem)</strong></p><p> - <code data-inline="true" spellcheck="false">/market</code> — live marketplace from on-chain <code data-inline="true" spellcheck="false">Minted</code> events; one-click Buy runs the full re-seal + <code data-inline="true" spellcheck="false">purchase()</code> paying 0.1 OG to the seller</p><p> - <code data-inline="true" spellcheck="false">/prompts</code> — console scans <code data-inline="true" spellcheck="false">totalMinted()</code> + <code data-inline="true" spellcheck="false">ownerOf</code> so minted-and-transferred-in tokens both appear; real re-seal on Sell; buyer-side <code data-inline="true" spellcheck="false">useEffect</code> auto-claims keys from <code data-inline="true" spellcheck="false">SealedKeyDelivered</code> events</p><p> - Mint dialog with explicit <strong>Tx 1 of 2</strong> (0G Storage) / <strong>Tx 2 of 2</strong> (mint) labels; receipt parsing injects the new tokenId instantly instead of waiting on the indexer</p><p> - Marketplace ↔ console deep-link for buyer-requested seller-initiated transfers</p><p></p><p> <strong>Seeded catalog</strong> — <code data-inline="true" spellcheck="false">scripts/seed-prompts.cjs</code> minted 4 sealed prompts (Legal Brief Writer, Solidity Auditor, Cold Email Generator, Trading Signal Analyzer) using the deployer wallet; the same data is</p><p> baked into <code data-inline="true" spellcheck="false">seedListings.ts</code> so the marketplace is non-empty in any browser.</p><p></p><p> <strong>Branding + docs</strong> — Rebranded the full app to <strong>0gPrompt</strong> (NavBar, Footer, layout, pitch deck, all marketing pages). Rewrote <code data-inline="true" spellcheck="false">README.md</code>, <code data-inline="true" spellcheck="false">demo.md</code>, <code data-inline="true" spellcheck="false">pending.md</code> around the new <code data-inline="true" spellcheck="false">purchase()</code> flow with an</p><p> ASCII flow diagram, security model, and explicit next-slice list (ECIES sealing to buyer pubkey, per-listing pricing, production oracle).</p><p></p>
<p>Bootstrapped. No fundraising to date — built solo during the hackathon.</p>