solana prediction market smart contract - market creation, liquidity, order matching, oracle settlement, dispute system
Solana Prediction Market Smart Contract
Prediction Market built on Solana using the Anchor framework. Users can create markets, place bets on Yes/No outcomes, resolve markets, and claim winnings proportionally minus a 1% platform fee.
Transasction
- Initialize Market
- Place Bet on Yes
- Place Bet on No
Features
- Create Markets: Initialize prediction markets with custom questions and end times
- Place Bets: Bet native SOL on Yes or No outcomes before the betting period ends
- Resolve Markets: Authorized resolution authority sets the true outcome
- Claim Winnings: Winners automatically receive proportional payouts based on their bet size
- Security Features:
Architecture
Core Components
- Market Account: Stores market state (question, totals, resolution status, fee percentage)
- Bet Account: Stores individual bet information (bettor, amount, outcome, claimed status)
- Instructions:
initialize_market: Create a new prediction market
- place_bet: Place a bet on Yes or No
- resolve_market: Resolve the market with the true outcome
- claim_winnings: Claim proportional winnings for winners
Solana-Specific Concepts
Program Derived Addresses (PDAs)
- Market PDA:
[b"market", creator, question_hash]- Ensures unique markets per creator/question - Bet PDA:
[b"bet", market, bettor]- Ensures unique bets per user/market
Account Validation
Anchor uses constraints to validate accounts:init: Creates a new accountpayer: Who pays for account creation rentspace: Account size in bytesseeds: PDA derivation seedsbump: PDA bump seed (stored for later use)
Prerequisites
- Rust (latest stable version)
- Solana CLI (v1.18+)
- Anchor (v0.31+)
- Node.js (v18+) and Yarn
- TypeScript (for tests)
Installation
- Clone the repository
git clone <your-repo-url>
cd prediction-market
- Install dependencies
yarn install
- Install Anchor (if not already installed)
cargo install --git https://github.com/coral-xyz/anchor avm --locked --force
avm install latest
avm use latest
- Build the program
anchor build
Testing
Local Testing
Run the test suite on a local validator:
# Start local validator (in separate terminal)
solana-test-validator
Run tests
anchor test
Devnet Testing
Test on Solana devnet:
# Configure for devnet
solana config set --url devnet
Deploy to devnet
anchor deploy --provider.cluster devnet
Run devnet tests
yarn test:devnet
How It Works
1. Initialize Market
Creator sets:- Question (e.g., "Will Bitcoin reach $100k by 2025?")
- End time for betting period
- Resolution authority (defaults to creator)
2. Place Bets
Users bet SOL on Yes or No before the end time:- Each user can have one bet per market
- Bets are stored in individual Bet accounts
- Market totals are updated automatically
3. Resolve Market
After the end time, the resolution authority sets the true outcome (Yes or No).4. Claim Winnings
Winners can claim their proportional share:- Payout Formula:
(userbet / winningpool) ร (total_pool - fee) - Fee: 1% deducted from total pool
- Example:
(50 / 100) ร 297 = 148.5 SOL
Project Structure
prediction-market/
โโโ programs/
โ โโโ prediction-market/
โ โโโ src/
โ โโโ lib.rs # Main program logic
โโโ tests/
โ โโโ prediction-market.ts # Local test suite
โโโ test-devnet.ts # Devnet test suite
โโโ migrations/
โ โโโ deploy.ts # Deployment script
โโโ Anchor.toml # Anchor configuration
โโโ README.md # This file
Security Features
- Time Validation
- Authorization
Signer constraint to verify signatures
- Reentrancy Protection
- Math Overflow Protection
checkedadd, checkedmul, etc.
- Returns MathOverflow error if overflow occurs
- Input Validation
Account Structures
Market Account
pub struct Market {
pub creator: Pubkey,
pub resolution_authority: Pubkey,
pub question: String,
pub end_time: i64,
pub resolved: bool,
pub outcome: Option<bool>,
pub totalyesbets: u64,
pub totalnobets: u64,
pub fee_percentage: u16, // In basis points (100 = 1%)
pub bump: u8,
}
Size: ~305 bytes
Bet Account
pub struct Bet {
pub bettor: Pubkey,
pub market: Pubkey,
pub amount: u64,
pub outcome: bool,
pub claimed: bool,
pub bump: u8,
}
Size: ~83 bytes
Deployment
Local Deployment
anchor build
anchor deploy
Devnet Deployment
anchor build
anchor deploy --provider.cluster devnet
Program ID
- Localnet:
3LHuBziG2Tp1UrxgoTAZDDbvDK46quk6T99kHkgt8UQg - Devnet:
3LHuBziG2Tp1UrxgoTAZDDbvDK46quk6T99kHkgt8UQg
Usage Examples
Initialize a Market
const question = "Will Bitcoin reach $100k by 2025?";
const endTime = new BN(Date.now() / 1000 + 86400); // 24 hours from now
const questionHash = hashQuestionToArray(question);
await program.methods .initializeMarket(question, endTime, questionHash) .accounts({ market: marketPDA, creator: creator.publicKey, systemProgram: SystemProgram.programId, }) .rpc();
Place a Bet
const betAmount = new BN(1 * LAMPORTSPERSOL); // 1 SOL
const outcome = true; // Yes
await program.methods .placeBet(betAmount, outcome) .accounts({ market: marketPDA, bet: betPDA, bettor: bettor.publicKey, systemProgram: SystemProgram.programId, }) .signers([bettor]) .rpc();
Resolve Market
const outcome = true; // Yes wins
await program.methods .resolveMarket(outcome) .accounts({ market: marketPDA, resolutionAuthority: authority.publicKey, }) .signers([authority]) .rpc();
Claim Winnings
await program.methods
.claimWinnings()
.accounts({
market: marketPDA,
bet: betPDA,
bettor: bettor.publicKey,
})
.signers([bettor])
.rpc();
Test Coverage
The test suite covers:
- Market initialization
- Placing bets on both sides
- Market resolution
- Claiming winnings
- Error cases:
License
ISC