Reflects the on-chain implementation as of the current
contracts/predict-iqsource.
- Initialization
- Market Lifecycle
- Betting
- Oracle & Resolution
- Disputes & Voting
- Governance & Upgrades
- Fees & Referrals
- Circuit Breaker
- Queries (Paginated)
- Error Codes
- Events
Bootstraps the contract. Can only be called once.
| Param | Type | Description |
|---|---|---|
admin |
Address |
Master admin account (must authorize) |
base_fee |
i128 |
Protocol fee in stroops |
Errors: AlreadyInitialized
create_market(creator, description, options, deadline, resolution_deadline, oracle_config, tier, native_token, parent_id, parent_outcome_idx) → Result<u64, ErrorCode>
| Param | Type | Description |
|---|---|---|
creator |
Address |
Market creator (must authorize) |
description |
String |
Human-readable market question |
options |
Vec<String> |
Outcome labels (max MAX_OUTCOMES_PER_MARKET = 32) |
deadline |
u64 |
Unix timestamp — betting closes |
resolution_deadline |
u64 |
Unix timestamp — resolution must occur by |
oracle_config |
OracleConfig |
Multi-oracle configuration (see below) |
tier |
MarketTier |
Basic | Pro | Institutional |
native_token |
Address |
SAC token used for bets |
parent_id |
u64 |
0 for independent markets; parent market ID for conditional |
parent_outcome_idx |
u32 |
Required parent outcome (ignored when parent_id = 0) |
Returns: new market_id
OracleConfig fields:
| Field | Type | Description |
|---|---|---|
oracle_address |
Address |
Deployed Pyth contract address |
feed_id |
String |
64-char hex-encoded 32-byte Pyth price feed ID |
min_responses |
Option<u32> |
Minimum oracle responses required; None defaults to 1 |
max_staleness_seconds |
u64 |
Max age of price data in seconds |
max_confidence_bps |
u64 |
Max confidence interval in basis points |
Errors: InvalidDeadline, TooManyOutcomes, InsufficientDeposit, MarketIdOverflow, MarketIdCollision, ParentMarketNotResolved, ParentMarketInvalidOutcome
Returns the full Market struct or None if not found.
Admin-only hard cancellation. Emits mkt_cncl.
Errors: NotAuthorized, MarketNotFound
Permissionless cleanup after the 30-day grace period post-resolution.
Errors: MarketNotFound, MarketStillActive, MarketNotResolved
Admin-only. Sets None | Basic | Pro | Institutional.
Admin-only deposit required to create a market.
Creator reclaims deposit after the dispute window closes without a challenge.
Errors: MarketNotFound, NotAuthorized, DisputeWindowStillOpen, MarketNotDisputed
| Param | Type | Description |
|---|---|---|
bettor |
Address |
Must authorize |
market_id |
u64 |
Target market |
outcome |
u32 |
Zero-based outcome index |
amount |
i128 |
Gross bet amount in token units |
token_address |
Address |
Must match market's token_address |
referrer |
Option<Address> |
Optional referral address |
Errors: MarketNotFound, MarketClosed, MarketNotActive, InvalidBetAmount, InvalidOutcome, ContractPaused, InvalidReferrer, AssetClawedBack, TransferFailed
Pull-model payout. Returns amount transferred.
Errors: MarketNotFound, MarketNotResolved, BetNotFound, NoWinnings, AlreadyClaimed
Refund on cancelled markets.
Errors: MarketNotFound, BetNotFound, AlreadyClaimed
Total staked on a specific outcome.
Unique bettor count per outcome (analytics).
Admin-only. oracle_id = 0 is the primary oracle. Supports multiple oracle sources per market.
Errors: NotAuthorized, MarketNotFound
Permissionless. Reads the oracle result and transitions the market to PendingResolution if conditions are met.
Errors: MarketNotFound, MarketNotActive, OracleFailure, StalePrice, ConfidenceTooLow, ResolutionNotReady
Permissionless. Moves PendingResolution → Resolved after the grace period.
Errors: MarketNotFound, MarketNotPendingResolution, GracePeriodActive, ResolutionDeadlinePassed
Admin-only resolution for disputed markets.
Errors: NotAuthorized, MarketNotFound, MarketNotDisputed
Admin fallback when community voting deadlocks (no 60% majority after 72-hour window).
Errors: NotAuthorized, MarketNotFound, MarketNotDisputed, VotingPeriodNotElapsed, NoMajorityReached
Admin-only. Minimum 24 hours. Default 72 hours.
Opens a dispute window. Requires contract to be unpaused.
Errors: MarketNotFound, MarketNotPendingResolution, DisputeWindowClosed, ContractPaused
Governance token holders vote on disputed outcome. Requires contract to be unpaused.
Errors: MarketNotFound, MarketNotDisputed, AlreadyVoted, InsufficientVotingWeight, GovernanceTokenNotSet, ContractPaused
Releases locked governance tokens after voting concludes.
Triggered by 2/3 Guardian majority.
Returns { votes_for: u32, votes_against: u32 }.
Range: 6 hours – 7 days. Default: 48 hours.
Errors: TimelockActive, UpgradeNotInitiated, AlreadyVotedOnUpgrade, UpgradeAlreadyPending, UpgradeHashInCooldown
Legacy single-guardian slot.
States: Closed | Open | HalfOpen | Paused
Admin-only. Clears error counters.
All paginated queries silently clamp limit to 100 (MAX_PAGE_LIMIT). Callers requesting more receive at most 100 records — no error is returned.
Returns all markets regardless of status, ordered by creation (ascending).
Filters by Active | PendingResolution | Disputed | Resolved | Cancelled. Iterates newest-first for fresher results.
| Code | Value | Description |
|---|---|---|
AlreadyInitialized |
1 | Contract already initialized |
NotAuthorized |
2 | Caller lacks required authorization |
GuardianNotSet |
3 | Guardian account not configured |
MarketNotFound |
4 | No market with the given ID |
MarketClosed |
5 | Market deadline has passed |
MarketStillActive |
6 | Market is still accepting bets |
MarketNotActive |
7 | Market is not in Active state |
MarketNotResolved |
8 | Market has not been resolved yet |
MarketNotDisputed |
9 | Market is not in Disputed state |
MarketNotPendingResolution |
10 | Market is not in PendingResolution state |
CannotChangeOutcome |
11 | Outcome is already finalized |
InvalidDeadline |
12 | Deadline is in the past or malformed |
DeadlinePassed |
13 | Action attempted after deadline |
ResolutionDeadlinePassed |
14 | Resolution deadline has elapsed |
ResolutionNotReady |
15 | Conditions for resolution not yet met |
GracePeriodActive |
16 | Grace period has not elapsed |
MarketIdOverflow |
17 | Market ID counter overflowed |
MarketIdCollision |
18 | Market ID already in use |
InvalidOutcome |
19 | Outcome index out of range |
TooManyOutcomes |
20 | Exceeds MAX_OUTCOMES_PER_MARKET (32) |
InvalidBetAmount |
21 | Bet amount is zero or below minimum |
InsufficientBalance |
22 | Caller token balance too low |
InsufficientDeposit |
23 | Creation deposit not met |
InvalidAmount |
24 | Generic invalid amount |
BetNotFound |
25 | No bet record for this bettor/market |
NoWinnings |
26 | Bettor did not back the winning outcome |
AlreadyClaimed |
27 | Winnings or refund already claimed |
OracleFailure |
28 | Oracle cross-contract call failed |
StalePrice |
29 | Price feed publish_time older than max_staleness_seconds |
ConfidenceTooLow |
30 | Oracle confidence interval exceeds max_confidence_bps |
InvalidTimestamp |
31 | Timestamp value is invalid |
AssetClawedBack |
32 | SAC token clawback reduced contract balance unexpectedly |
TransferFailed |
33 | SAC token transfer failed programmatically |
DisputeWindowClosed |
34 | Dispute window has expired |
DisputeWindowStillOpen |
35 | Dispute window has not yet closed |
AlreadyVoted |
36 | Address has already cast a vote |
InsufficientVotes |
37 | Not enough votes to proceed |
InsufficientVotingWeight |
38 | Voter's governance token balance too low |
NoMajorityReached |
39 | No outcome reached the 60% majority threshold |
GovernanceTokenNotSet |
40 | Governance token address not configured |
TimelockActive |
41 | Upgrade timelock has not elapsed |
UpgradeNotInitiated |
42 | No pending upgrade to act on |
AlreadyVotedOnUpgrade |
43 | Address already voted on this upgrade |
UpgradeAlreadyPending |
44 | An upgrade proposal is already pending |
UpgradeHashInCooldown |
45 | This wasm hash is in the 7-day cooldown period |
ParentMarketNotResolved |
46 | Conditional market's parent is not yet resolved |
ParentMarketInvalidOutcome |
47 | Parent market resolved to a different outcome |
ContractPaused |
48 | Contract is paused via circuit breaker |
InvalidReferrer |
49 | Referrer address is invalid or self-referral |
VotingPeriodNotElapsed |
50 | Admin fallback called before 72-hour voting window elapsed |
All events follow the topic layout:
- Topic 0: Event name (short symbol, ≤ 9 chars)
- Topic 1:
market_id: u64(primary indexer key;0for contract-level events) - Topic 2: Triggering address
| Event | Topic Symbol | Data Payload |
|---|---|---|
| MarketCreated | mkt_creat |
(description: String, num_outcomes: u32, deadline: u64) |
| BetPlaced | bet_place |
(outcome: u32, amount: i128) |
| DisputeFiled | disp_file |
new_deadline: u64 |
| ResolutionFinalized | resolv_fx |
(winning_outcome: u32, total_payout: i128) |
| RewardsClaimed | reward_fx |
(amount: i128, token_address: Address, is_refund: bool) |
| VoteCast | vote_cast |
(outcome: u32, weight: i128) |
| CircuitBreakerTriggered | cb_state |
state: String |
| OracleResultSet | oracle_ok |
outcome: u32 |
| OracleResolved | orcl_res |
outcome: u32 |
| MarketFinalized | mkt_final |
winning_outcome: u32 |
| DisputeResolved | disp_res |
winning_outcome: u32 |
| MarketCancelled (admin) | mkt_cncl |
() |
| MarketCancelledVote (community) | mk_cn_vt |
() |
| ReferralReward | ref_rwrd |
amount: i128 |
| ReferralClaimed | ref_claim |
amount: i128 |
| CircuitBreakerAuto | cb_auto |
error_count: u32 |
| MonitoringStateReset | mon_reset |
(previous_error_count: u32, previous_last_observation: u64) |
| FeeCollected | fee_colct |
amount: i128 |
| AdminFallbackResolution | adm_fbk |
winning_outcome: u32 |
| CreatorReputationSet | rep_set |
(old_score: u32, new_score: u32) |
| CreationDepositSet | dep_set |
(old_amount: i128, new_amount: i128) |
Note:
MonitoringStateReset,CircuitBreakerTriggered,CircuitBreakerAuto, andFeeCollectedusemarket_id = 0and the contract address as Topic 2.CreatorReputationSetuses(symbol, creator)with nomarket_id.CreationDepositSetuses(symbol,)only.