Private bids, guaranteed onchain delivery.
CipherBid is a Vickrey NFT auction on Starknet where every accepted bidder locks the same STRK collateral cap through STRK20. The actual bid stays sealed until reveal. Settlement sends the NFT to the winner at the greater of the reserve or second-highest valid bid, and every refund, surplus, and seller payment returns through private STRK20 claims.
Open the live mainnet auction · Watch the final demo · Read the transaction ledger · Use the presentation script
Many auction demos hide a bid with a hash but do not prove the bidder can pay. Escrowing each bidder's exact amount fixes funding but leaks the bid through the public token transfer.
CipherBid locks the same public 4 STRK cap for both bidders. Observers see funded bids with equal collateral, but not whether the sealed bid is 2 STRK or 4 STRK. After reveal, the contract calculates the Vickrey price, transfers the escrowed NFT in the same settlement transaction, and accounts for every remaining STRK claim.
Atomic settlement means all-or-nothing delivery. Winner selection, second-price accounting, and the NFT transfer succeed together or the transaction reverts. There is no accepted state where CipherBid records a winner but leaves the NFT with the seller.
Verified mainnet result: auction
1788040057342completed two private equal-cap bids, two reveals, second-price settlement, atomic NFT delivery, bidder claims, and the final seller claim. Five published CipherBid transactions touched the canonical STRK20 pool.
| Minimal commit/reveal demo | CipherBid |
|---|---|
| A hash can be submitted without funded collateral | Every accepted bid moves the same real STRK cap through the live STRK20 pool |
| Exact escrow can leak the bid before reveal | Equal collateral hides which value at or below the cap was committed |
| Delivery can remain a separate manual step | The NFT enters custody at creation and moves to the winner inside settlement |
| Refunds often use public transfers | Loser refund, winner surplus, and seller proceeds use STRK20 open-note claims |
| Recovery is left outside the demo | Password-encrypted credentials bind to network, contract, auction, role, and claim handle |
| Success is usually shown with local tests | Mainnet receipts, CipherBid events, pool traces, NFT ownership, and zero residual accounting |
A STRK20 privacy_invoke withdraws tokens from the privacy pool to the helper through a public ERC-20 edge. Escrowing each bidder's variable bid would reveal that amount before the reveal phase. CipherBid therefore locks the same cap for every accepted bidder. The public transfer proves every bid is funded without disclosing whether the sealed bid is 2 STRK, 4 STRK, or another value at or below the cap.
This is STRK20-funded sealed bidding with equalized real collateral. It is not an unfunded hash-only auction, and it does not claim bids remain private after reveal.
| Component | Address / transaction |
|---|---|
| AuctionHouse | 0x01b32af8bab712ede82117b8ff1b8866e09798f6c81edc255ffe59dd42e4843e |
| DemoERC721 | 0x05c7080c583304469e853e472d46a20448ff82bf9ee4c87a8efabc35f8177e1f |
| Demo NFT | Token ID 99 |
| STRK20 pool | 0x040337b1af3c663e86e333bab5a4b28da8d4652a15a69beee2b677776ffe812a |
| STRK token | 0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d |
| AuctionHouse declaration | 0x552781e5ecb2ab9826474c8395ca5fd2f534ce6155367ab67ae195f5e2c9dc6 |
| DemoERC721 declaration | 0x01efc7df78014f252d346af3b88a5035b002cf005079604f6e3bf9df0f1fa9b |
Deployment readback confirmed the reviewed class hashes, canonical pool and STRK token, a maximum of 32 bidders, and initial deployer ownership of NFT 99. The verified lifecycle now proves token 99 was delivered to Bidder B during settlement. See the deployment evidence and machine-readable manifest.
The production frontend is live at https://sourcesenseitherealone.github.io/cipherbid/. Its source-controlled deployment workflow uses immutable action pins, least-privilege token permissions, and only public mainnet configuration. The main deployment, workflow, Pages settings, and public browser routes were independently read back.
The exportable live-auction route is /auction?id=<positive-u64>. It validates one auction ID, reads public Starknet state in the browser, verifies the deployed class/configuration and NFT custody, then renders wallet controls. Ready X still owns private-note discovery, proving, signing, and submission.
The final 2:24 public demo video follows this page through equal collateral, the 2/4 STRK result, private claims, and atomic delivery. The presentation script remains available for the complete talk track and judge Q&A.
The bounded mainnet demo uses one seller, two separate Ready X accounts, and one read-only observer:
| Term | Value |
|---|---|
| Reserve | 1 STRK |
| Equal collateral cap | 4 STRK |
| Bidder A sealed bid | 2 STRK |
| Bidder B sealed bid | 4 STRK |
| Verified winner | Bidder B |
| Verified clearing price | 2 STRK |
| Loser refund | 4 STRK |
| Winner surplus | 2 STRK |
| Seller proceeds | 2 STRK, claimed |
| Final house balance | 0 STRK |
| Bidding window | 10 minutes |
| Reveal window | 5 minutes |
Both bidders shielded 24 STRK and passed the ten-block maturity gate before the timed auction started. Public readiness verified registration, deposit amount, and maturity only. Ready X remained authoritative for unspent private-note balance.
flowchart LR
UI["CipherBid web app<br/>public reads and action descriptors"]
Wallet["Ready X<br/>keys, notes, proving, signing"]
RPC["Starknet RPC<br/>state and receipt readback"]
Pool["STRK20 pool<br/>private ingress and claims"]
House["AuctionHouse<br/>NFT custody and Vickrey accounting"]
NFT["ERC-721<br/>token 99"]
Recovery["Encrypted recovery bundle<br/>held by the user"]
UI -->|read public state| RPC
RPC --> House
UI -->|Wallet API request| Wallet
Wallet -->|private action| Pool
Pool -->|privacy_invoke| House
Wallet -->|standard lifecycle call| House
House -->|custody and settlement| NFT
UI -.->|encrypt and export| Recovery
Recovery -.->|import for reveal or claim| UI
CipherBid never receives the wallet's viewing key, private notes, proof witness, or signer key. Ready X owns those operations. The web app constructs bounded public descriptors, keeps active auction credentials in memory, encrypts recovery exports, and verifies every submitted transition through public RPC readback.
flowchart TD
A["Seller escrows NFT and creates auction"] --> B["Bidder A and Bidder B each lock the same 4 STRK cap"]
B --> C["Bids remain sealed until the reveal window"]
C --> D["Bidder A reveals 2 STRK; Bidder B reveals 4 STRK"]
D --> E["AuctionHouse selects Bidder B and clears at 2 STRK"]
E --> F["Settlement transfers token 99 to Bidder B"]
F --> G["Loser refund, winner surplus, and seller proceeds return through STRK20"]
G --> H["Final AuctionHouse STRK balance: 0"]
The next research direction is to extend CipherBid from one-unit NFT sales to multi-unit token launches. Participants would submit funded sealed demand, reveal after the bidding window, and settle allocations at an onchain clearing price.
That extension needs a new allocation and settlement contract, including multi-unit accounting and claim rules. It is roadmap work, not functionality claimed by the current verified ERC-721 deployment.
A bid commitment binds the domain tag, Starknet chain ID, AuctionHouse address, auction ID, bid amount, random nonce, claim handle, and NFT recipient. Recovery material is also bound to network, chain ID, deployment, and auction ID before reveal or claim.
- Only the configured STRK20 pool may call
privacy_invoke. - Ingress is accounted from the helper's actual STRK balance delta.
- Every accepted bidder locks the same cap.
- Bidder count and settlement work are bounded.
- NFT custody is established during auction creation and delivery is part of settlement.
- Claims are one-time and commitment-bound.
- All
u256 → u128conversions are checked. - External interactions follow checks-effects-interactions and reentrancy protection.
| Public | Private before reveal |
|---|---|
| Auction terms, NFT, reserve, cap, and deadlines | Bid amount and random bid nonce |
| STRK20 registration and public deposits | Private-note ownership and note-selection witnesses |
| Identical collateral transfer amount | Wallet viewing key and proof witness |
| Bid count and transaction timing | Claim secret |
| Revealed bids, winner, and clearing price | Bidder's main-wallet linkage inside the pool |
| Withdrawals, open-note edges, and direct lifecycle calls | Recovery plaintext outside its active in-memory use |
Ready X owns private-note discovery, proof generation, signing, and private transaction submission. CipherBid never requests a viewing key or private-note witness. The browser does hold the active bid credential briefly to construct the interaction and encrypt an exportable recovery bundle; plaintext secrets must never enter browser storage, logs, analytics, URLs, clipboard, Git, or a backend.
CipherBid protects the bid amount until reveal and prevents an unfunded winner, but it does not provide perfect anonymity:
- deposits, withdrawals, open-note amounts, timing, and public account activity remain visible;
- distinctive amounts or tightly timed setup can shrink the anonymity set;
- opening a channel near a public action may create timing linkage;
- every valid reveal makes the bid amount public by design;
- a malicious web page could substitute dapp-built Wallet API actions before the wallet prompt, so users must verify target and amount in Ready X;
- wallet, prover, relayer, RPC, screening, and browser availability remain operational dependencies;
- private balances cannot be verified by the dapp;
- the present contracts and signer configuration are a bounded hackathon demo, not an audited production deployment.
STRK20's auditor disclosure mechanism can reveal activity under its protocol policy; a viewing key can read but cannot spend funds.
contracts/ Cairo AuctionHouse and DemoERC721
web/ Next.js application and Wallet API integration
context/ Product, architecture, security, and stack decisions
docs/evidence/ Secret-free specifications and public readbacks
strk20.json Final verified submission metadata
- Node.js 24
- pnpm 10
- Cairo compiler 2.20.0
- Scarb 2.20.1
- Starknet Foundry 0.63.0
- Ready X for real STRK20 wallet flows
npx --yes pnpm@10.18.1 --dir web install --frozen-lockfile
cd web
npx --yes pnpm@10.18.1 exec tsx scripts/configure-mainnet-env.ts \
--deployment-record ../docs/evidence/mainnet/deployment.json \
--writeThe configuration command writes only public deployment values and refuses to overwrite an existing .env.local.
cd web
npx --yes pnpm@10.18.1 exec next dev --webpack -p 4110Open:
http://127.0.0.1:4110/— auction browserhttp://127.0.0.1:4110/auction?id=1— public auction reader; ID1remains unavailable until a real auction existshttp://127.0.0.1:4110/create— seller creation flowhttp://127.0.0.1:4110/demo/setup— Ready X bidder shielding
cd contracts
scarb fmt --check
scarb build
snforge testnpx --yes pnpm@10.18.1 --dir web format:check
npx --yes pnpm@10.18.1 --dir web lint
npx --yes pnpm@10.18.1 --dir web typecheck
npx --yes pnpm@10.18.1 --dir web test
npx --yes pnpm@10.18.1 --dir web test:e2e
npx --yes pnpm@10.18.1 --dir web pages:verify
npx --yes pnpm@10.18.1 --dir web build
CIPHERBID_PAGES_BUILD=1 npx --yes pnpm@10.18.1 --dir web buildMainnet write scripts default to plan-only and require explicit --execute:
cd web
npx --yes pnpm@10.18.1 run deploy:mainnet
npx --yes pnpm@10.18.1 run auction:preflight:mainnet
npx --yes pnpm@10.18.1 exec tsx scripts/create-mainnet-auction.ts --auction-id <id>Do not add --execute until the printed plan, signer, network, public bidder readiness, recovery destination, and remaining release budget have been verified. Never commit .env.local, wallet state, recovery bundles, runtime evidence, browser state, or signing material.
- Evidence index
- Mainnet deployment
- Verified mainnet transaction ledger
- Verified mainnet auction lifecycle
- Final public demo video evidence
- Live demo presentation script
- Mainnet release candidate
- Canonical demo matrix
- Lifecycle specification
- Security invariants
- Hackathon requirements matrix
- Sepolia rehearsal
strk20.json contains two verified contracts, five successful pool-touching CipherBid transactions, the clean-browser-verified auction URL, and the public 2:24 YouTube demo.
The sprint MVP supports one STRK payment token, ERC-721 assets, one-unit Vickrey auctions, and at most 32 bidders. It intentionally excludes a broad marketplace, first-price or multi-unit auctions, ERC-1155, off-chain delivery, user accounts, a database, a custom prover, and custom privacy cryptography.