Contract Reference
Complete API reference for all PredictionLabs smart contracts.
MarketFactory
Immutables
| Name | Type | Description |
|---|---|---|
CTF | IConditionalTokens | Gnosis CTF address |
State
| Name | Type | Description |
|---|---|---|
marketCount | uint256 | Total markets created |
markets | mapping(bytes32 => Market) | Market data by conditionId |
pendingResolutionCount | mapping(bytes32 => uint256) | conditionId → count of pending resolution attempts |
Constants
| Name | Value | Description |
|---|---|---|
VOID_TIMEOUT | 90 days | Permissionless void after deadline + 90 days (no pending) |
EMERGENCY_VOID_TIMEOUT | 180 days | Emergency void regardless of pending |
Types
Market (struct)
| Field | Type |
|---|---|
questionId | bytes32 |
deadline | uint64 |
outcomeSlotCount | uint8 |
resolved | bool |
creator | address |
resolver | address |
Functions
createMarket(string question, uint256 outcomeSlotCount, uint256 deadline, address resolver) → bytes32 conditionId
Creates a new prediction market with a per-market resolver.
outcomeSlotCount: 2–255deadline: must be in the futureresolver: address of the resolver module for this market
resolveMarket(bytes32 conditionId, uint256[] payouts)
Called by the market's resolver to finalize the outcome. Reports payouts to the CTF.
notifyResolutionInitiated(bytes32 conditionId)
Called by a resolver to signal that a resolution attempt has started. Increments pendingResolutionCount.
notifyResolutionFinalized(bytes32 conditionId)
Called by a resolver to signal that a resolution attempt has finished (settled or disputed). Decrements pendingResolutionCount.
forceVoid(bytes32 conditionId)
Permissionless void. Anyone can call.
- After deadline + 90 days with
pendingResolutionCount == 0 - After deadline + 180 days regardless of pending count
isTrading(bytes32 conditionId) → bool
True if market exists and is not resolved.
isResolvable(bytes32 conditionId) → bool
True if deadline has passed and market is not resolved.
Events
| Event | Parameters |
|---|---|
MarketCreated | conditionId (indexed), questionId (indexed), creator (indexed), resolver, outcomeSlotCount, deadline, question |
MarketResolved | conditionId (indexed), resolver (indexed) |
MarketVoided | conditionId (indexed) |
ResolutionInitiated | conditionId (indexed), resolver (indexed) |
ResolutionFinalized | conditionId (indexed), resolver (indexed) |
OrderBook
Immutables
| Name | Type | Description |
|---|---|---|
CTF | IConditionalTokens | Gnosis CTF address |
FACTORY | MarketFactory | MarketFactory address |
TREASURY | Treasury | Treasury address |
COLLATERAL | IERC20 | USDC address |
State
| Name | Type | Description |
|---|---|---|
nextOrderId | uint256 | Counter for order IDs |
orders | mapping(uint256 => Order) | All orders by ID |
Constants
| Name | Value | Description |
|---|---|---|
MIN_ORDER_COST | 1e4 | 0.01 USDC minimum order cost; minimum fill amount (shares) |
PRICE_SCALE | 1e6 | $1.00 = 1e6 |
MAX_AMOUNT | 1e18 | Maximum shares per order |
FEE_BPS | 10 | 0.1% fee |
BPS_DENOMINATOR | 10000 | Basis point denominator |
Types
Side (enum)
| Value | Description |
|---|---|
BUY (0) | Buying outcome tokens with USDC |
SELL (1) | Selling outcome tokens for USDC |
Order (struct)
| Field | Type |
|---|---|
maker | address |
side | Side |
cancelled | bool |
conditionId | bytes32 |
outcomeIndex | uint256 |
price | uint256 |
amount | uint256 |
filled | uint256 |
Functions
placeBuyOrder(bytes32 conditionId, uint256 outcomeIndex, uint256 price, uint256 amount) → uint256 orderId
Place a limit buy order. Transfers USDC from caller.
price: 1 to 999999amount: shares wanted- Cost locked:
price * amount / 1e6
placeSellOrder(bytes32 conditionId, uint256 outcomeIndex, uint256 price, uint256 amount) → uint256 orderId
Place a limit sell order. Transfers outcome tokens from caller (requires CTF approval).
price: minimum acceptable price
placeBuyOrders(bytes32[] conditionIds, uint256[] outcomeIndexes, uint256[] prices, uint256[] amounts) → uint256[] orderIds
Batch buy order placement.
fillBuyVsBuy(uint256 buyId0, uint256 buyId1, uint256 fillAmount)
Match two BUY orders on opposite outcomes. Combined USDC splits into tokens. fillAmount is in shares (6 decimals, e.g. 100e6 = 100 shares).
- Both must be BUY, same market, different outcomes
price0 + price1 >= 1e6(prices cross)- Surplus refunded proportionally
fillBuyVsSell(uint256 buyId, uint256 sellId, uint256 fillAmount)
Match a BUY against a SELL on the same outcome. Executes at seller's price.
- Buyer's price >= seller's price
- Buyer gets tokens, seller gets USDC minus fee
- Buyer's excess USDC refunded
cancelOrder(uint256 orderId)
Cancel your own order. Refunds remaining USDC (BUY) or tokens (SELL).
cancelOrders(uint256[] orderIds)
Batch cancel.
cancelExpiredOrder(uint256 orderId)
Cancel any order on a resolved market. Anyone can call.
onERC1155Received / onERC1155BatchReceived
ERC-1155 receiver hooks. Only accepts tokens from CTF.
supportsInterface(bytes4 interfaceId) → bool
Returns true for ERC-165 (0x01ffc9a7) and ERC-1155 receiver (0x4e2312e0).
Events
| Event | Parameters |
|---|---|
OrderPlaced | orderId (indexed), maker (indexed), conditionId (indexed), outcomeIndex, side, price, amount |
OrderFilled | orderId (indexed), matchedOrderId (indexed), fillAmount |
OrderCancelled | orderId (indexed) |
Treasury
Constants
| Name | Value |
|---|---|
FEE_BPS | 10 (0.1%) |
BPS_DENOMINATOR | 10000 |
Immutables
| Name | Type | Description |
|---|---|---|
RECIPIENT | address | Fee recipient, set at deploy |
Functions
calculateFee(uint256 amount) → uint256
Returns the fee for a given amount. Rounds up.
withdraw(IERC20 token)
Sends full token balance to RECIPIENT. Anyone can call.
- Reverts:
ZeroAddress(custom error),NoFees(custom error)
Events
| Event | Parameters |
|---|---|
FeesWithdrawn | token (indexed), amount |
NegRiskAdapter
Immutables
| Name | Type | Description |
|---|---|---|
FACTORY | MarketFactory | MarketFactory address |
State
| Name | Type | Description |
|---|---|---|
nextMarketId | uint256 | Counter for market IDs |
Functions
createMultiOutcomeMarket(string question, string[] outcomeLabels, uint256 deadline, address resolver) → uint256 marketId
Creates N binary markets from a multi-outcome question. Each binary leg is created on the MarketFactory with the specified resolver.
- 2–64 outcomes, no duplicates, no empty labels, question max 1024 bytes
getOutcomeConditionId(uint256 marketId, uint256 outcomeIndex) → bytes32
Returns the binary conditionId for a specific outcome.
getOutcomeCount(uint256 marketId) → uint256
Returns the number of outcomes.
getAllConditionIds(uint256 marketId) → bytes32[]
Returns all binary conditionIds.
getOutcomeLabel(uint256 marketId, uint256 outcomeIndex) → string
Returns the label for an outcome.
isResolved(uint256 marketId) → bool
True when ALL underlying binary markets are resolved.
Events
| Event | Parameters |
|---|---|
MultiOutcomeMarketCreated | marketId (indexed), creator (indexed), resolver (indexed), question, outcomeCount, deadline, binaryConditionIds |
BaseResolver (abstract)
Abstract base contract for building custom resolvers. Provides factory reference, common validations, and payout helpers.
Immutables
| Name | Type | Description |
|---|---|---|
FACTORY | MarketFactory | MarketFactory address |
Internal Functions
| Function | Description |
|---|---|
_requireResolver(bytes32 conditionId) | Reverts NotThisResolver if this contract isn't the market's resolver |
_requireResolvable(bytes32 conditionId) | Reverts NotResolvable if before deadline or already resolved |
_resolveOutcome(bytes32 conditionId, uint256 winnerIndex) | Builds payouts and calls factory.resolveMarket(). type(uint256).max = void (equal payouts). Reverts InvalidOutcome if index out of bounds. |
_notifyInitiated(bytes32 conditionId) | Calls factory.notifyResolutionInitiated() |
_notifyFinalized(bytes32 conditionId) | Calls factory.notifyResolutionFinalized() |
Errors
| Error | When |
|---|---|
ZeroAddress | Factory address is zero in constructor |
NotThisResolver | Contract is not the resolver for the given market |
NotResolvable | Market is before deadline or already resolved |
InvalidOutcome | Winner index >= outcome count (and not type(uint256).max) |
UMAResolver
Immutables
| Name | Type | Description |
|---|---|---|
FACTORY | MarketFactory | MarketFactory address |
ORACLE | IOptimisticOracleV3 | UMA OOv3 address |
BOND_TOKEN | IERC20 | Bond/collateral token (USDC) |
State
| Name | Type | Description |
|---|---|---|
activeAssertions | mapping(bytes32 => bytes32) | conditionId → active assertionId |
assertions | mapping(bytes32 => Assertion) | assertionId → assertion data |
Constants
| Name | Value | Description |
|---|---|---|
LIVENESS | 7200 | 2-hour challenge window |
BOND_AMOUNT | 750e6 | 750 USDC bond floor |
Types
Assertion (struct)
| Field | Type |
|---|---|
conditionId | bytes32 |
assertedOutcome | uint256 |
asserter | address |
Functions
assertOutcome(bytes32 conditionId, uint256 assertedOutcome)
Assert which outcome won. Caller pays bond.
- Market must be resolvable (deadline passed, not resolved)
- No other active assertion on this market
assertedOutcome: any index from 0 tooutcomeSlotCount - 1, ortype(uint256).maxfor VOID
assertOutcomeFor(bytes32 conditionId, uint256 assertedOutcome, address asserter)
Assert on behalf of another address. Bond pulled from msg.sender, refund goes to asserter.
settleAssertion(bytes32 assertionId)
Poke UMA to settle a liveness-expired assertion. Anyone can call.
bondAmount() → uint256
Returns the effective bond: max of 750 USDC and UMA's current minimum.
Callbacks (called by UMA only)
assertionResolvedCallback(bytes32 assertionId, bool assertedTruthfully)
Called when assertion settles. If truthful, resolves the market via factory.resolveMarket().
assertionDisputedCallback(bytes32 assertionId)
Called when assertion is disputed. Clears the active assertion slot.
Events
| Event | Parameters |
|---|---|
ResolutionAsserted | conditionId (indexed), assertionId (indexed), assertedOutcome, asserter |
MarketResolved | conditionId (indexed), winningOutcome |
MarketVoided | conditionId (indexed) |
AssertionDisputed | conditionId (indexed), assertionId (indexed) |
AssertionRejected | conditionId (indexed), assertionId (indexed) |
KalshiResolver
Immutables
| Name | Type | Description |
|---|---|---|
FACTORY | MarketFactory | MarketFactory address |
ORACLE | IOptimisticOracleV3 | UMA OOv3 address |
BOND_TOKEN | IERC20 | Bond/collateral token (USDC) |
State
| Name | Type | Description |
|---|---|---|
assertions | mapping(bytes32 => Assertion) | Assertion data by assertionId |
activeAssertions | mapping(bytes32 => bytes32) | conditionId → active assertionId |
kalshiTickers | mapping(bytes32 => bytes32) | conditionId → Kalshi ticker |
Functions
linkMarket(bytes32 conditionId, bytes32 ticker)
Links an PredictionLabs market to a Kalshi ticker. Must be called before asserting.
assertOutcome(bytes32 conditionId, uint256 assertedOutcome)
Assert which outcome won. Caller pays bond.
assertOutcomeFor(bytes32 conditionId, uint256 assertedOutcome, address asserter)
Assert on behalf of another address. Bond pulled from msg.sender, refund goes to asserter.
settleAssertion(bytes32 assertionId)
Poke UMA to settle a liveness-expired assertion. Anyone can call.
bondAmount() → uint256
Returns the effective bond.
Callbacks (called by UMA only)
assertionResolvedCallback(bytes32 assertionId, bool assertedTruthfully)
Called when assertion settles. If truthful, resolves the market.
assertionDisputedCallback(bytes32 assertionId)
Called when assertion is disputed. Clears the active assertion slot.
PolymarketResolver
Immutables
| Name | Type | Description |
|---|---|---|
FACTORY | MarketFactory | MarketFactory address |
CTF | IConditionalTokens | Gnosis CTF address (shared with Polymarket) |
State
| Name | Type | Description |
|---|---|---|
polymarketConditions | mapping(bytes32 => bytes32) | PredictionLabs conditionId → Polymarket conditionId |
Functions
linkMarket(bytes32 conditionId, bytes32 polymarketConditionId)
Links an PredictionLabs market to a Polymarket condition. The condition does not need to be resolved at link time.
resolve(bytes32 conditionId)
Reads payouts from the Gnosis CTF (payoutNumerators/payoutDenominator) and resolves the market via factory.resolveMarket(). The Polymarket condition must be resolved on the CTF before calling.