Overview
ThePredictionMarketV2 contract manages the complete lifecycle of prediction markets, from creation through resolution and payout. It implements on-chain Levenshtein distance calculation for winner determination and features pull-based fee collection to prevent griefing attacks.
Contract Address: TBD (Deployment pending)
Constants
| Constant | Value | Description |
|---|---|---|
PLATFORM_FEE_BPS | 700 | Platform fee in basis points (7%) |
MIN_BET | 0.001 ether | Minimum bet amount |
BETTING_CUTOFF | 1 hour | Betting closes 1 hour before market end |
MIN_SUBMISSIONS | 2 | Minimum submissions required for resolution |
MAX_TEXT_LENGTH | 280 | Maximum prediction text length (characters) |
Market Creation
createMarket
Creates a new prediction market for a social media actor.Social media handle being predicted (e.g., “@elonmusk”)
Market duration in seconds. Must be between 1 hour and 30 days.
The ID of the newly created market
MarketCreated(uint256 indexed marketId, string actorHandle, uint256 endTime, address creator)
Errors:
InvalidDuration()- Duration not between 1 hour and 30 days
Submission Management
createSubmission
Submit a prediction and stake ETH on it.The market ID to submit to
Your prediction of what the actor will say. Must be 1-280 characters.
ETH amount to stake. Must be at least
MIN_BET (0.001 ETH).The ID of the newly created submission
SubmissionCreated(uint256 indexed submissionId, uint256 indexed marketId, address submitter, string predictedText, uint256 amount)
Errors:
MarketNotFound()- Market ID doesn’t existMarketAlreadyResolved()- Market already resolvedMarketEnded()- Market end time passedBettingCutoffPassed()- Within 1 hour of market endInsufficientBet()- Bet below minimumEmptyPrediction()- Prediction text is emptyPredictionTooLong()- Prediction exceeds 280 characters
Market Resolution
resolveMarket
Resolve a market by providing the actual text. Only callable by contract owner.The market ID to resolve
The actual text the actor posted
MarketResolved(uint256 indexed marketId, uint256 winningSubmissionId, string actualText, uint256 winningDistance)
Resolution Logic:
- Winner determined by minimum Levenshtein distance to actual text
- First submitter wins ties (deterministic)
- Requires at least 2 submissions
MarketNotFound()- Market ID doesn’t existMarketAlreadyResolved()- Market already resolvedMarketNotEnded()- Market end time not reachedMinimumSubmissionsNotMet()- Less than 2 submissions
Payout Claims
claimPayout
Claim payout for a winning submission.The submission ID to claim payout for
PayoutClaimed(uint256 indexed submissionId, address indexed claimer, uint256 amount)
Payout Calculation:
- Winner receives:
totalPool * (100 - 7) / 100= 93% of pool - Platform receives:
totalPool * 7 / 100= 7% fee - Fees accumulated for pull-based withdrawal
SubmissionNotFound()- Submission ID doesn’t existMarketNotEnded()- Market not resolved yetNotWinningSubmission()- Not the winning submissionAlreadyClaimed()- Payout already claimedTransferFailed()- ETH transfer failed
refundSingleSubmission
Refund the only submission when market ends with single entry. Prevents unfair fee loss when there’s no competition.The market with single submission
SingleSubmissionRefunded(uint256 indexed marketId, uint256 indexed submissionId, address submitter, uint256 amount)
Errors:
MarketNotFound()- Market ID doesn’t existMarketAlreadyResolved()- Market already resolvedMarketNotEndedForRefund()- Market hasn’t ended yetNotSingleSubmission()- Market has more than 1 submissionAlreadyClaimed()- Already refundedTransferFailed()- ETH transfer failed
Fee Management
withdrawFees
Withdraw accumulated fees using pull-based pattern.FeesWithdrawn(address indexed recipient, uint256 amount)
Errors:
NoFeesToWithdraw()- No fees available for callerTransferFailed()- ETH transfer failed
View Functions
getMarketSubmissions
Get all submission IDs for a market.The market ID
Array of submission IDs for the market
getUserSubmissions
Get all submission IDs for a user.The user address
Array of submission IDs for the user
getMarketDetails
Get comprehensive market information.The market ID
The social media handle being predicted
Unix timestamp when the market ends
Total ETH staked in the market (in wei)
Whether the market has been resolved
The winning submission ID (0 if unresolved)
Address that created the market
All submission IDs for this market
getSubmissionDetails
Get comprehensive submission information.The submission ID
The market this submission belongs to
Address that created the submission
The predicted text
ETH staked on this prediction (in wei)
Whether payout has been claimed
Admin Functions
setFeeRecipient
Update the fee recipient address. Only callable by contract owner.New address to receive platform fees
pause
Pause the contract in emergency situations. Only callable by contract owner.createMarket and createSubmission cannot be called.
unpause
Unpause the contract. Only callable by contract owner.emergencyWithdraw
Emergency withdraw for unresolved markets. Returns funds to submitters. Only callable by contract owner.The market to emergency withdraw from
- Only callable 7 days after market end time
- Market must not be resolved
- Returns full stake to each submitter (no fees taken)
MarketNotFound()- Market ID doesn’t existMarketAlreadyResolved()- Market already resolvedMarketNotEnded()- Not 7 days past market end
Utility Functions
levenshteinDistance
Calculate Levenshtein (edit) distance between two strings. Pure function, callable off-chain.First string
Second string
The edit distance between the strings