Inspiration

What it does

How we built it

Challenges we ran into

Accomplishments that we're proud of

What we learned

What's next for ShadowBid

Inspiration

Open NFT auctions expose every bid immediately, enabling copy-trading, anchoring, sniping, and collusion. ShadowBid explores a better boundary: keep bid amounts private while making custody, deadlines, settlement authorization, and final ownership auditable.

What it does

ShadowBid is a cross-chain sealed-bid NFT auction. An ERC-721 is escrowed on EVM. Each bidder supplies a private amount and salt to a Midnight Compact circuit, which publishes only a domain-bound commitment hash. EffectStream deterministically indexes public facts from Midnight and EVM into one auditable read model. After the deadline, a trusted coordinator authorizes settlement with an EIP-712 signature, and the EVM contract transfers the NFT after verifying exact payment, deadlines, domain, nonce, expiry, replay protection, and winner identity. Losing bid amounts are never published.

How we built it

The Compact contract has eight circuits across three bidder slots: register_auction, commit_bid_0/1/2, close_commitments, and open_and_consume_0/1/2. Amount and salt remain private inputs and are never disclosed. The recorded 8/13/11 run generated genuine ZK proofs for all eight calls.

The EVM contract handles ERC-721 escrow and signature-authorized settlement. EffectStream ingests append-only public observations from both chains, folds them through a deterministic reducer, materializes them in PGLite/Postgres, and serves the React dashboard through Fastify.

What Midnight proves—and does not prove

Midnight proves that each commitment is well-formed and domain-bound and that each opening genuinely opens its commitment. It does not prove that the winner has the maximum bid: the circuits never compare amounts. The trusted coordinator selects and signs the result. Ethereum verifies that EIP-712 authorization, not a Midnight winner-computation proof. EffectStream is deterministic indexing, not a trustless bridge or settlement authority.

Privacy

Private before settlement: all bid amounts, salts, and opening witnesses. Public: commitment hashes, lifecycle flags, nullifiers, counts, seller, token, deadlines, reserve, addresses, and transaction metadata. After settlement the winner and winning amount become public by design; the two losing amounts and losing bidder identities remain unpublished. We verified this against the real settled run across every API route, the served frontend, and the rendered DOM including attributes.

Challenges

The hardest bugs were at chain boundaries: an incorrect Compact binding import, missing consumed flags in the live ledger reader, and an EVM timestamp update that attempted to move time backward after proof transactions had mined blocks. A live database run also exposed a SQL parameter-offset bug and a regex that misread PostgreSQL ::int casts.

Accomplishments

  • Recorded three-bidder auction with private bids 8, 13, and 11
  • Eight genuine Compact proof calls with real proving/verifier keys
  • Final NFT ownership and EffectStream SETTLED projection verified
  • 42/42 orchestrated checks, 45 focused tests, 8 Forge tests, and 4 Compact tests
  • Fail-closed settlement checks for missing, malformed, stale, replayed, forged, or domain-mismatched data

What we learned

Privacy claims should be measured on actual public surfaces, not inferred from architecture. We also learned to state ZK and cross-chain trust boundaries precisely: deterministic indexing is not bridging, and commitment-opening proofs are not winner-computation proofs.

Limitations and future work

The UI is currently read-only and the recorded run is harness-driven. Three commitments used one local development wallet. The Compact instance has three fixed slots and supports one auction per deployment. The coordinator lacks production multi-party approval, key management, rate limiting, and durable audit. Future work includes proof-backed winner selection with deterministic tie rules and EVM-address binding, scalable bidder storage, authenticated/time-bound Compact transitions, wallet-backed UI writes, and production coordinator hardening.

Built With

Share this project:

Updates

Submission history