Summary
Implement position settlement: converting a locked outcome (#68) into per-position entitlements, permissionlessly and in O(1) per call, with no loop over all positions.
What to build
Settlement rules depend on terminal_cause:
Strict-majority result:
- Positions on the winning side recover their principal.
- Positions on the losing side, and positions that never revealed, are forfeited entirely.
- The forfeited pool is distributed among winning positions in proportion to their weight:
reward_i = floor((s_i * forfeited_pool) / recipient_weight), payout_i = s_i + reward_i, where recipient_weight is the final winning-side weight.
Optimistic timeout default:
- Every revealed position, on either side, recovers its principal.
- Only non-revealed positions are forfeited.
- That forfeited pool is distributed pro rata among all revealed positions (both sides), using the same
reward_i formula, with recipient_weight = total revealed weight.
Mechanics required in both cases:
settle(id: u64, address: Address) is permissionless (any caller may settle any known position) and must be callable in any order without changing results: every position's payout uses the same forfeited_pool and recipient_weight captured at outcome-lock time, so settlement order never matters.
- Settlement does not itself move tokens. It marks the position settled and accrues
payout_i to a Credit(id, address) record. See the withdrawal issue for the separate step that actually transfers tokens.
- Once
recipient_weight reaches zero (all recipient positions settled), any remaining indivisible dust from integer division accrues to a deterministic party: the winning asserter or disputer after a strict-majority result, or the asserter after a timeout default. If forfeited_pool == 0, skip the dust step entirely.
- All arithmetic must be checked/overflow-safe and must conserve the pool exactly:
funded_total == withdrawn_total + accrued_credit + unsettled_entitlements must hold after every settlement.
Depends on
#68 (needs a locked terminal_cause and final_outcome to settle against).
Summary
Implement position settlement: converting a locked outcome (#68) into per-position entitlements, permissionlessly and in O(1) per call, with no loop over all positions.
What to build
Settlement rules depend on
terminal_cause:Strict-majority result:
reward_i = floor((s_i * forfeited_pool) / recipient_weight),payout_i = s_i + reward_i, whererecipient_weightis the final winning-side weight.Optimistic timeout default:
reward_iformula, withrecipient_weight= total revealed weight.Mechanics required in both cases:
settle(id: u64, address: Address)is permissionless (any caller may settle any known position) and must be callable in any order without changing results: every position's payout uses the sameforfeited_poolandrecipient_weightcaptured at outcome-lock time, so settlement order never matters.payout_ito aCredit(id, address)record. See the withdrawal issue for the separate step that actually transfers tokens.recipient_weightreaches zero (all recipient positions settled), any remaining indivisible dust from integer division accrues to a deterministic party: the winning asserter or disputer after a strict-majority result, or the asserter after a timeout default. Ifforfeited_pool == 0, skip the dust step entirely.funded_total == withdrawn_total + accrued_credit + unsettled_entitlementsmust hold after every settlement.Depends on
#68 (needs a locked
terminal_causeandfinal_outcometo settle against).