Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 

Repository files navigation

SealBid

"Every token launch, NFT drop, and auction on Solana is front-run before it settles. SealBid makes that cryptographically impossible."


What is SealBid?

SealBid is a MEV-proof auction primitive for Solana. It solves a fundamental protocol-level flaw in every on-chain auction today: bids are public the moment they're submitted, which means bots can read your bid in the mempool, outbid you by 1 lamport, and you lose every time.

This isn't a UI problem. No frontend fix can solve it. SealBid solves it at the protocol layer using a commit-reveal scheme — bids are cryptographically hidden until the commit window closes, making front-running impossible by design.

SealBid is not a DEX or a marketplace. It is a general primitive — an SDK that any Solana dApp can plug into in under 50 lines of code.


The Problem

Every on-chain auction on Solana today works like this:

  1. Bidder submits a bid transaction
  2. The transaction is visible in the mempool before it settles
  3. A bot reads the bid, constructs a higher bid, and gets it included first
  4. The honest bidder loses — every time

This affects:

  • NFT drops and sales
  • Token launches and IDOs
  • On-chain job markets and freelance boards
  • Any dApp that requires competitive bidding

Existing solutions like Darklake address this at the DEX level. SealBid is a 10x larger story — a general primitive that any dApp can use.


How SealBid Works

SealBid uses a three-phase commit-reveal protocol.

Phase 1 — Commit

The bidder generates a cryptographic commitment client-side:

commitment = keccak256(bid_amount || salt)

Only the hash goes on-chain. USDC is locked in a PDA escrow. No one — not bots, not validators — can read the bid amount from the commitment hash.

Phase 2 — Reveal

After the commit window closes, bidders submit their plaintext bid_amount and salt. The Solana program verifies:

hash(bid_amount || salt) == stored_commitment

If a bidder fails to reveal within the reveal window, their bond is slashed. This is the anti-griefing mechanic that prevents commit-without-reveal attacks.

Phase 3 — Settlement

The highest valid revealed bid wins. Tokens transfer via SPL. All losing bidders receive their USDC refunded atomically in the same transaction.


Architecture

┌─────────────────────────────────────────────────────────┐
│                        Frontend                         │
│         Next.js 14 + TypeScript + Wallet Adapter        │
│                                                         │
│  commitment = keccak256(bid_amount || salt)              │
│  (computed in browser — raw bid never leaves client)    │
└────────────────────────┬────────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────────┐
│                     SealBid SDK                         │
│              TypeScript wrapper library                 │
│                                                         │
│  SealBid.create()   — initialize auction                │
│  SealBid.commit()   — submit commitment + lock funds    │
│  SealBid.reveal()   — submit plaintext bid + salt       │
│  SealBid.settle()   — resolve winner, refund losers     │
└────────────────────────┬────────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────────┐
│               Solana Smart Contract                     │
│                  Rust + Anchor                          │
│                                                         │
│  Instructions:                                          │
│    commit_bid      — store hash, lock USDC in PDA       │
│    reveal_bid      — verify hash, record plaintext bid  │
│    settle_auction  — pick winner, atomic SPL transfers  │
│                                                         │
│  Accounts:                                              │
│    Auction PDA     — auction state, timing, config      │
│    Bidder PDA      — per-bidder commitment + escrow     │
└─────────────────────────────────────────────────────────┘

Tech Stack

Layer Technology
Smart Contract Rust, Anchor Framework
Token Transfers SPL Token Program
State Management Program Derived Addresses (PDAs)
Frontend Next.js 14, TypeScript
Wallet Integration Solana Wallet Adapter (Phantom, Backpack)
Client-side Hashing @noble/hashes (keccak256)
Network Solana Devnet / Mainnet

Smart Contract

Three instructions handle the entire auction lifecycle.

commit_bid

pub fn commit_bid(
    ctx: Context<CommitBid>,
    commitment: [u8; 32],   // keccak256(bid_amount || salt)
    escrow_amount: u64,     // USDC locked — must be >= max possible bid
) -> Result<()>
  • Stores commitment hash in the bidder's PDA
  • Transfers USDC from bidder wallet to escrow PDA
  • Reverts if commit window has closed

reveal_bid

pub fn reveal_bid(
    ctx: Context<RevealBid>,
    bid_amount: u64,
    salt: [u8; 32],
) -> Result<()>
  • Recomputes keccak256(bid_amount || salt) on-chain
  • Verifies it matches the stored commitment
  • Records bid_amount as the bidder's valid bid
  • Slashes bond if called outside the reveal window

settle_auction

pub fn settle_auction(
    ctx: Context<SettleAuction>,
) -> Result<()>
  • Iterates all revealed bids, picks highest
  • Transfers tokens to winner via SPL
  • Refunds all losing bidder escrows atomically
  • Marks auction as settled

SDK

Any Solana dApp can integrate SealBid in under 50 lines:

import { SealBid } from "@sealbid/sdk";
import { keccak256 } from "@noble/hashes/sha3";

const client = new SealBid({ connection, wallet });

// 1. Create an auction
const auction = await client.create({
  tokenMint: MINT_ADDRESS,
  tokenAmount: 100,
  commitDuration: 300,  // 5 minutes
  revealDuration: 180,  // 3 minutes
});

// 2. Commit a bid (hash computed client-side, raw bid never leaves browser)
const salt = crypto.getRandomValues(new Uint8Array(32));
const commitment = keccak256(encode(bidAmount, salt));

await client.commit({
  auctionId: auction.id,
  commitment,
  escrowAmount: bidAmount,
});

// 3. Reveal after commit window closes
await client.reveal({
  auctionId: auction.id,
  bidAmount,
  salt,
});

// 4. Settle — winner gets tokens, losers get refunds
await client.settle({ auctionId: auction.id });

Why Solana

SealBid is purpose-built for Solana because:

  • PDAs allow deterministic, per-bidder escrow accounts without a central custodian
  • Atomic multi-instruction transactions let settlement and refunds happen in a single transaction
  • SPL Token Program handles USDC and token transfers natively
  • Sub-second finality makes the reveal phase fast enough to be practical in a real auction

The same design is significantly more cumbersome on Ethereum.


Why SealBid Beats the Competition

Project Scope Approach Limitation
Darklake DEX only Order privacy Single use case
Urani DeFi layer MEV discouraged Not cryptographic
SealBid Any dApp MEV impossible
  • Darklake is DEX-specific. SealBid is a general primitive.
  • Urani discourages MEV at the app layer. SealBid makes it cryptographically impossible.
  • ZK-based approaches (e.g., ProofPass) require off-chain proving infrastructure. SealBid uses only on-chain hashing — no circuits, no oracles, no trusted setup.

Demo

The live demo shows the difference in two side-by-side browser tabs.

Normal auction:

  1. Bidder A submits a bid
  2. Bot reads the bid in the mempool
  3. Bot submits a higher bid and wins
  4. Bidder A loses — every time

SealBid auction:

  1. Bidder A submits a commitment hash — bot sees nothing
  2. Commit window closes
  3. Both bidders reveal
  4. Winner is settled on-chain, loser refunded instantly

The demo also shows the SDK integration — one file, under 50 lines, dropping SealBid into an existing dApp.


Use Cases

Because SealBid is a primitive, not a product, any Solana dApp can use it:

  • NFT marketplaces — sealed-bid NFT auctions, no sniper bots
  • Token launchpads — fair IDO allocation, no front-running
  • Freelance / job boards — blind bid job markets on-chain
  • Grant programs — transparent but private proposal funding rounds
  • DAO governance — sealed voting before public tally

Project Structure

sealbid/
├── programs/
│   └── sealbid/
│       └── src/
│           ├── lib.rs              # Program entry point
│           ├── instructions/
│           │   ├── commit_bid.rs
│           │   ├── reveal_bid.rs
│           │   └── settle_auction.rs
│           └── state/
│               ├── auction.rs
│               └── bidder.rs
├── sdk/
│   └── src/
│       ├── index.ts                # SealBid client
│       ├── commit.ts
│       ├── reveal.ts
│       └── settle.ts
├── app/
│   ├── pages/
│   │   ├── index.tsx               # Auction list
│   │   ├── create.tsx              # Create auction
│   │   └── auction/[id].tsx        # Bid + reveal UI
│   └── components/
│       ├── CommitForm.tsx
│       ├── RevealForm.tsx
│       └── AuctionStatus.tsx
├── tests/
│   └── sealbid.ts                  # Anchor integration tests
├── Anchor.toml
└── package.json

Getting Started

Prerequisites

  • Rust (rustup)
  • Solana CLI (solana-install)
  • Anchor CLI (cargo install --git https://github.com/coral-xyz/anchor anchor-cli)
  • Node.js 18+

Build and Deploy

# Clone the repo
git clone https://github.com/your-username/sealbid
cd sealbid

# Install dependencies
npm install

# Build the Anchor program
anchor build

# Run tests on local validator
anchor test

# Deploy to devnet
anchor deploy --provider.cluster devnet

Run the Frontend

cd app
npm install
npm run dev

Open http://localhost:3000.


Security Properties

Property Guarantee
Bid confidentiality Bids are hidden until commit window closes — no on-chain or mempool leakage
Commit binding A bidder cannot change their bid after committing — the hash binds them
Reveal enforcement Non-reveal results in bond slash — griefing is economically punished
Atomic settlement Winner transfer and loser refunds happen in one transaction — no partial states
No trusted third party All logic is on-chain — no oracle, no off-chain server, no admin key

Honest Complexity

SealBid deliberately avoids unnecessary cryptographic complexity. Commit-reveal is well-understood, auditable, and buildable. The innovation is applying it as a general Solana primitive with:

  • A clean SDK abstraction
  • A bond/slash mechanism for reveal enforcement
  • Atomic SPL settlement in a single instruction

No ZK circuits. No off-chain provers. No trusted setup. Just hash functions and PDAs.


Built at Colosseum Hackathon

SealBid was built as a hackathon project targeting the Solana ecosystem. The design prioritizes:

  • Demonstrability — the problem and solution are visible in a live demo
  • Defensibility — the cryptography is simple enough to explain and audit under questioning
  • Generality — it is infrastructure, not a single application

About

Your bid goes in a vault. Nobody sees it until the moment it counts.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages