Settlement
Settlement is the process of distributing winnings after a market resolves. This document covers the settlement flow, payout calculations, and claiming process.
Settlement Flow
Payout Rules
Winner Calculation
| Outcome | Winning Share | Payout per Share |
|---|---|---|
| UP | YES | 1.0000 USDC |
| DOWN | NO | 1.0000 USDC |
Loser Calculation
Losing shares have no redemption value:
| Outcome | Losing Share | Payout per Share |
|---|---|---|
| UP | NO | 0 USDC |
| DOWN | YES | 0 USDC |
Position Settlement
Settlement Transaction
pub fn settle_position(ctx: Context<SettlePosition>) -> Result<()> {
let market = &ctx.accounts.market;
let position = &ctx.accounts.position;
require!(market.outcome.is_some(), SeesawError::MarketNotResolved);
let payout = match market.outcome.unwrap() {
Outcome::Up => position.yes_shares,
Outcome::Down => position.no_shares,
};
// Transfer payout from vault to user
transfer_tokens(
&ctx.accounts.vault,
&ctx.accounts.user_token_account,
payout,
)?;
// Close position account, return rent
close_account(
&ctx.accounts.position,
&ctx.accounts.user,
)?;
Ok(())
}
Example Scenarios
Scenario 1: Full Win
Alice's Position:
├── YES shares: 100
├── NO shares: 0
└── Cost basis: 60 USDC (bought at 0.60)
Market resolves: UP
Payout: 100 × 1.00 = 100 USDC
Profit: 100 - 60 = 40 USDC (67% return)
Scenario 2: Full Loss
Bob's Position:
├── YES shares: 0
├── NO shares: 50
└── Cost basis: 20 USDC (bought at 0.40)
Market resolves: UP
Payout: 0 × 1.00 = 0 USDC
Loss: 20 USDC (100% loss)
Scenario 3: Mixed Position
Carol's Position:
├── YES shares: 80
├── NO shares: 30
└── Cost basis: 55 USDC
Market resolves: UP
Payout: 80 × 1.00 = 80 USDC
NET profit: 80 - 55 = 25 USDC
Solvency Guarantee
The protocol can always pay winners because:
- Every share is backed by collateral
- Vault holds
max(yes, no)USDC - Only one side wins
Claiming Process
Via Web App
- Navigate to Portfolio tab
- Find resolved markets with claimable positions
- Click Claim button
- Approve transaction in wallet
- USDC and rent transferred to wallet
Via CLI
seesaw settle \
--market <MARKET_ADDRESS> \
--position <POSITION_ADDRESS>
Via SDK
import { settlePosition } from '@seesaw/sdk';
const tx = await settlePosition({
market: marketPubkey,
user: userPubkey,
});
await sendAndConfirmTransaction(connection, tx, [userKeypair]);
Batch Settlement
For efficiency, positions can be settled in batches:
Crank operators typically batch settlements for gas efficiency.
Rent Recovery
Position accounts are closed during settlement:
Account Lifecycle:
├── Created: User pays ~0.002 SOL rent
├── Active: Holds position data
└── Closed: Rent returned to user
Net cost: 0 SOL (rent fully recovered)
Edge Cases
Zero Position
If a position has 0 shares of both types:
- No payout (0 USDC)
- Account still closes
- Rent returned
Unclaimed Positions
Positions can be claimed anytime after resolution:
- No expiration on claims
- Market stays open until all claimed
- Crank incentive for settlement
Already Settled
If settle_position called twice:
- First call succeeds
- Second call fails (account doesn't exist)
- No double-payment possible
Market Closure
After all positions settled:
Close Conditions
- Market is RESOLVED
- All position accounts settled (closed)
- Vault balance is 0
Rent Distribution
| Account | Rent Returns To |
|---|---|
| Market | Market creator |
| Vault | Market creator |
| Orderbook | Market creator |
| Position | Position owner |
Settlement Fees
Seesaw charges no settlement fee:
| Operation | Fee |
|---|---|
| Settlement | 0% |
| Rent | Returned |
| Claim | Gas only |
This maximizes user returns and encourages participation.