Real-time prediction markets on Solana — zero fees, sub-second settlement, powered by MagicBlock Ephemeral Rollups.
Every existing prediction market on Solana charges a transaction fee every time you take or adjust a position. For markets with short lifespans and frequent rebalancing, fees add up fast — killing the UX and making micro-positions economically unviable. Settlement is also typically delayed: a crank has to manually process each market, often minutes after expiry.
EPOCH is a price-direction prediction market protocol where users bet on whether a crypto asset (SOL, BTC, ETH) will be above or below a target price at a specific time. The entire trading lifecycle runs on a MagicBlock Ephemeral Rollup (ER) — a temporary off-chain execution environment that is cryptographically backed by Solana L1.
- Creating a market delegates its Solana PDAs to an ER session. The session lifetime matches the market lifetime.
- Taking and adjusting positions happen inside the ER — completely free and confirmed in under a second.
- Settlement fires atomically via a Magic Action when the Pyth oracle confirms the outcome, committing final state back to Solana L1 in a single transaction.
Solana L1 (Base Layer)
├── Market PDA — initialized here, delegated to ER on creation
├── Vault PDA — holds locked SOL for the duration of the market
└── Position PDAs — per-user, delegated to ER alongside the market
MagicBlock Ephemeral Rollup (live session)
├── takePosition — free, sub-second, updates YES/NO pool sizes
├── adjustPosition — free, sub-second, rebalances your position
└── commit_and_settle — Magic Action → atomically undelegates + settles on L1
Pyth Oracle (PriCems5tHihc6UDXDjzjeawomAwBduWMGAi8ZUjppd)
└── SOL/USD · BTC/USD · ETH/USD price feeds at settlement
The key insight is that all high-frequency operations are off-chain during the session, but every state transition is eventually consistent with Solana L1 — no separate bridge, no wrapped assets, no trust assumptions beyond the Solana validator set.
initializeMarket → Sets up Market PDA with question, asset, target price, direction, expiry
initializePosition → Creates creator's Position PDA
delegatePosition → Delegates position account to the ER network
delegateMarket → Delegates market account to ER validator, starts the session
takePosition → Bet YES (price will be above target) or NO (price will be below)
adjustPosition → Add to an existing position anytime before expiry
Probability is derived from pool sizes in real time:
prob_yes = yes_total / (yes_total + no_total)
[crank] Polls markets approaching expiry
[Pyth oracle] Fetches confirmed price at the expiry timestamp
commit_and_settle → Magic Action fires: undelegates all accounts + commits final state to L1
withdrawWinnings → Winners claim proportional share of the losing pool
payout = your_deposit × (total_pool / winning_pool)
| Property | Without ER | With ER (EPOCH) |
|---|---|---|
| Fee per position | ~0.000005 SOL | Free |
| Confirmation time | ~400ms–2s | <100ms |
| Settlement finality | Solana L1 | Solana L1 (atomic) |
| Trust model | On-chain | On-chain (ER backed by L1) |
Ephemeral Rollups let EPOCH offer the UX of a CEX — instant, free order updates — without sacrificing the trust model of Solana. When the market closes, the ER session ends and state collapses back to L1 as if it never left.
EPOCH/
├── programs/epoch/ # Anchor program (Rust)
│ └── src/
│ ├── instructions/ # initialize_market, take_position, settle, withdraw...
│ ├── state/ # Market, Position, Vault PDAs
│ └── errors.rs
├── tests/ # Full lifecycle integration tests (10/10 passing)
├── crank/ # Off-chain settlement crank (TypeScript)
│ └── src/index.ts # Polls expiring markets, fetches Pyth price, fires settlement
└── app/ # React frontend
└── src/
├── components/ # MarketCard, CreateMarketModal, PositionPanel, ProbabilityCurve
├── context/ # MarketsContext (real-time polling, ER + base layer merge)
├── lib/ # program.ts, oracle.ts, connections.ts
└── pages/ # Home, Markets, Market, HowItWorks, Docs
| Property | Value |
|---|---|
| Program ID | C6nt5YvgdgNKETYgHQF9Dm8XQdAreU3n5Pk4CHmrQVvu |
| Network | Solana Devnet |
| ER Validator | MAS1Dt9qreoRMQ14YQuhg8UTZMMzDdKhmkZMECCzk57 |
| Oracle | Pyth Lazer (PriCems5tHihc6UDXDjzjeawomAwBduWMGAi8ZUjppd) |
| Supported Assets | SOL/USD · BTC/USD · ETH/USD |
- Rust + Solana CLI (
platform-tools v1.54) - Anchor CLI
0.32 - Node.js 20+
# Install dependencies
yarn install
# Build the Anchor program
anchor build
# Run the full test suite against devnet
anchor test --skip-local-validatorAll 10 tests cover the complete market lifecycle:
- Market initialization and delegation to ER
- Position taking and adjustment inside the ER session
- Oracle-based settlement via Magic Action
- Winnings withdrawal on L1
cd crank
npm install
cp ../.env.example .env # fill in your wallet path
npm startThe crank polls every 500ms, finds markets at expiry, reads the Pyth oracle price, and fires commit_and_settle.
cd app
npm install
npm run devConnect a Phantom wallet on Solana Devnet to create markets and take positions.
| Layer | Technology |
|---|---|
| Smart contract | Rust · Anchor 0.32 |
| Rollup SDK | @magicblock-labs/ephemeral-rollups-sdk |
| Price oracle | Pyth Lazer on-chain feeds |
| Frontend | React 19 · Vite · TailwindCSS v4 |
| Charts | Recharts |
| Wallet | @solana/wallet-adapter |
| Animations | Framer Motion · GSAP |
EPOCH demonstrates that high-frequency financial applications are practical on Solana today — without L2 bridges, without wrapped tokens, and without sacrificing composability with the base layer. Every market that runs on EPOCH:
- Generates zero gas cost for users during the trading period
- Settles deterministically via a verifiable oracle price
- Returns all funds to L1 with no manual withdrawal from a sidechain
The same pattern applies beyond prediction markets — any application that benefits from free, fast, ephemeral state (games, order books, auctions, live events) can use this architecture on Solana today.
