Settlement
Finalizing a market and redeeming winnings.
Once the challenge window elapses without a successful dispute, the market is ready to finalize.
Finalization routes fees and moves the market to Finalized; winners then claim pro‑rata payouts.
Finalizing
if (await client.markets.canFinalize(marketAddress)) {
await client.markets.finalize({ marketAddress });
}Permissionless — anyone can call it. Requires:
- Status is
ResolvedPendingFinality. - The challenge window has fully elapsed.
In one transaction the contract computes creator + platform fees against the total pool,
transfers them, flips status to Finalized, and emits MarketFinalized + FeesPaid.
Because it's permissionless, most hosts run a lightweight cron that finalizes ripe markets so participants don't pay gas on a housekeeping call before redeeming. A minimal worker:
import { MarketsClient } from "@sdk.markets/sdk";
const client = new MarketsClient({ publicClient, walletClient });
for (const address of knownMarketAddresses) {
if (await client.markets.canFinalize(address)) {
await client.markets.finalize({ marketAddress: address });
console.log("finalized", address);
}
}Redeeming
await client.markets.redeem({ marketAddress });Available only on Finalized markets. Pays the caller their pro‑rata share of the post‑fee pool,
computed against their stake on the winning option.
Payout formula:
payout = userStake[winningOption]
* (totalPool - creatorFee - platformFee)
/ optionPool[winningOption]- Callers with zero stake on the winning option revert. They didn't win.
- Each address can redeem once per market;
hasRedeemed[caller]guards re‑entry. - Rounding is standard integer division — dust accrues to the contract and is unrecoverable. This is typically single‑digit wei and not worth addressing.
Emits:
event Redeemed(address user, uint256 payoutAmount);Refunding (voided markets)
If the market voided instead of finalizing, use refund() instead of redeem(). See
disputes.
A worked example
Market with three participants on a two‑option question, 1% creator fee, 1% platform fee (combined 200 bps = 2%):
| Participant | Stake | Option |
|---|---|---|
| A | 100 USDC | Yes |
| B | 200 USDC | Yes |
| C | 300 USDC | No |
Total pool: 600 USDC. Winning option: Yes. Fees: 2% × 600 = 12 USDC. Payout pool: 588 USDC.
- A redeems
100 / 300 × 588 = 196 USDC(net +96). - B redeems
200 / 300 × 588 = 392 USDC(net +192). - C redeems nothing (net −300).
Creator receives 6 USDC, platform receives 6 USDC.
Edge cases
- No winners. If nobody staked on the winning option,
optionPool[winningOption]is zero andredeemwould divide by zero. In practice this is impossible in any market with real activity, but if you're stress‑testing: the contract reverts onredeemand no payouts go out. The pool remains locked. Hosts should surface this in UI as a "bad market" case and steer creators away from options nobody picks. - Partial redeem is not supported.
redeempays the full winning‑option stake share in one call. - Stakes across options. If a participant staked on both the winning and a losing option, only the winning stake counts toward the redeem computation. The losing stake is absorbed into the pool like any other losing stake.