EscalationGame

Escrows outcome REP, raises the running resolution cost, detects non-decision, and settles local or carried deposits. EscalationGame source contract

Read surface

Base getters are securityPool, repToken, activationTime, nonDecisionThresholdAttoRep, startBondAttoRep, nonDecisionTimestamp, nonDecisionState, forkContinuation, forkElapsedAtStart, forkResumedAt, fixedQuestionOutcome, nodes, disputeStakedRepByVaultAttoRep, totalDisputeStakedAttoRep, ordinarySettlementInitialized, ordinaryWinningReserveAttoRep, ordinarySettlementForkThresholdAttoRep, creditedSurplusAttoRep, and winnerHaircutPaidByFork. Ordinary settlement fixes the winner liability and threshold; losing local deposits and escrow read as zero afterward, while raw historical nodes remain stored. The fallback forwards every selector other than the two signed deposits to EscalationGameClaimDelegate, which provides the reads rootClaimSourceGame, getInheritedClaimAllocation, and getUnresolvedClaimInterval, plus getClaimCheckpointProgress, getClaimCheckpointState, getClaimCheckpointWitnessSegment, getReusableClaimCheckpoint, getClaimIntervalTransform, and isClaimHistoryFrozen. Allocation reads inspect at most eight ancestors; deeper histories require permissionless checkpoint preparation. Central portfolio reporter claims keep identity coordinates across live branches and resolve their interval without ancestor traversal; their membership proofs and per-branch nullifiers still apply. getClaimCheckpointProgress distinguishes stored completion from readiness through the bounded read path. getClaimCheckpointState returns initialization, the pending commitment, the reused ancestor, and the current four-coordinate interval. getClaimCheckpointWitnessSegment returns the canonical source, prior commitment, first step, and length of the active segment; at most eight local transform reads reconstruct the batch from current state. getReusableClaimCheckpoint exports a completed interval and its excluded immediate-source anchor; descendants select caches only along their canonical lineage for the same claim tuple. The allocation read returns source principal, retained principal, reward-interval length, and the cumulative reward endpoint after compaction of consumed principal prefixes. The reward interval is the deposit’s range within its outcome’s cumulative deposits: its start is the returned endpoint minus the returned length. It determines which portion enters the reward calculation; the length is not a payable reward. Exported principal intervals compact consumed prefixes, while reward positions remain unshifted by prior claims. Allocations within a game stay fixed in every claim order. disputeStakedRepByVaultAttoRep is nominal reporter principal, not collateral value. getDisputeBackingAttoRep returns actual game REP; getVaultDisputeBackingAttoRep credits ordinary reports only for their contribution retained after source surplus, and returns zero for continuation claims. Inherited carry remains aggregate commitment state until proof settlement. Use previewDepositOnOutcome, computeIterativeAttritionCostAttoRep, computeTimeSinceStartFromAttritionCostAttoRep, totalCostAttoRep, getEscalationGameEndDate, getQuestionResolution, getFinalQuestionResolution, hasReachedNonDecision, canTriggerOwnFork, getBindingCapitalAttoRep, getOutcomeBalancesAttoRep, getDepositsByOutcome, getDepositsByOutcomeLength, forkCarrySnapshotInitialized, forkCarrySnapshotOutcomesInitialized, getOutcomeState, getForkCarrySnapshot, getForkCarryRoots, isForkCarryFundingComplete, getCarryLeafPageByOutcome, getProofConsumedCarriedDepositIndexesByOutcome, getLocalUnresolvedPrincipalByVaultAndOutcome, and getForkedEscrowByVaultAndOutcome for calculations, lifecycle authorization, pages, carry state, and escrow. getCarryLeafPageByOutcome limits visited nodes by maxEntries, including consumed nodes; empty or short pages may return a nonzero continuation cursor. Wallet reports and finalized withdrawals route through SecurityPool; after an ordinary game starts, wallet-funded deposits use depositRepOnOutcome, depositRepOnOutcomeWithPermit, or depositRepOnOutcomeWithAuthorization and mint no pool backing units.

State-changing interactions

Each call lists its parameter names in ABI order. The contract index defines the columns. Rows marked "through fallback()" are not in the compiled ABI: the fallback forwards the two signed deposit selectors to EscalationGameDepositDelegate and every other unknown selector to EscalationGameClaimDelegate by delegatecall, and returns or reverts with the delegate output. A call restricted to the owning pool or its forker reverts without reason data for any other caller. For central portfolio custody, report REP is held in the reporter ledger, independently of provider REP. Unrelated resumed continuations accept wallet-funded deposits. Fixed-outcome continuations end exactly three days after the child response anchor, which is the native parent fork time plus nine weeks; late materialization does not extend it. Other continuation deadlines retain their inherited elapsed time and minimum response period. The signed elapsed offset is negative when the parent fork interrupts the three-day activation delay; that remaining delay is preserved, and attrition stays zero until it expires. A later native fork interrupts unresolved reporting before any fixed outcome can be returned. totalCostAttoRep freezes attrition at the recorded universe fork time; a continuation whose universe forked before resume retains its inherited elapsed offset without adding wall-clock time. The scheduled deadline is the last second before the forward curve strictly exceeds binding capital, including integer-rounding plateaus; reporter and settlement books schedule that same cutoff. An unresolved parent cannot become final later. Per-question REP exports reject central custody.

Transaction Caller Main prerequisites State or asset effect Primary signals
start(startBondAttoRep, nonDecisionThresholdAttoRep) Immutable owner, the EscalationGameFactory, only (Only owner), during atomic deployment Game not already started, and nonDecisionThresholdAttoRep > startBondAttoRep > 0 (Invalid game start). Initializes a local game and sets activation three days after deployment. For ordinary pool games, the factory lowers an oversized configured bond to nonDecisionThresholdAttoRep - 1 before this call. GameStarted
startFromFork(startBondAttoRep, nonDecisionThresholdAttoRep, elapsedAtFork, fixedQuestionOutcome, winnerHaircutPaidByFork, forkCarryInitialBackingAttoRep) Immutable owner, the EscalationGameFactory, only (Only owner), during atomic continuation deployment Game not already started, and nonDecisionThresholdAttoRep > startBondAttoRep > 0 (Invalid game start); elapsedAtFork is a signed number of seconds between minus three days and seven weeks, inclusive (Invalid fork elapsed time). Initializes a paused continuation with inherited elapsed time, an optional fixed matching child outcome, and immutable fork-time escalation-haircut and backing accounting. It does not start the remaining clock until resumeFromFork. GameContinuedFromFork
resumeFromFork() Owning SecurityPool only (Only pool) Fork-continuation mode; not previously resumed; aggregate REP funding complete (isForkCarryFundingComplete). All three carry outcomes must be initialized (Fork snapshot incomplete), even for empty history. When the canonical factory records nonzero initial backing, the live reporter balance must cover that actual escrow after source surplus and native fork burn, minus valid direct pre-resume exports. Without recorded initial backing, it must cover effective inherited unresolved principal plus local unresolved principal across all three outcomes. Resumes once carry funding is complete. Standalone continuations use the transaction timestamp and deadline max(rebasedCurveEnd, forkResumedAt + 3 days). Bound continuations use the fixed portfolio response anchor; when their outcome is fixed, the deadline is exactly anchor plus three days, otherwise inherited attrition and the minimum response interval apply. Late materialization never moves the anchor. Final resolution also checks whether the native universe forked before that deadline. ForkContinuationResumed
depositRepOnOutcome(outcome, maximumDepositAttoRep) Any REP holder Current game is ordinary or a resumed portfolio continuation without a fixed outcome; game unresolved; pool operational; universe unforked; outcome non-None; caller allowance to this game covers the accepted REP; preview accepts a positive amount within the remaining threshold room. Transfers accepted REP from the caller into dispute escrow and appends its nominal deposit and carry leaf, without minting reporter backing units. Ordinary games release increases in the minimum outcome balance to vested portfolio REP income. Continuations do not release this ordinary surplus. REP Transfer, LocalDepositAppended, DepositOnOutcome, EscalationSurplusAccrued when the ordinary minimum increases, and NonDecisionReached when the deposit reaches non-decision
depositRepOnOutcomeWithPermit(outcome, maximumDepositAttoRep, deadline, v, r, s) through fallback() Any child-universe REP holder The depositRepOnOutcome game, pool, and preview prerequisites; the pool universe is not genesis (Genesis REP does not support permit); the permit succeeds or the caller allowance to this game covers the previewed amount (Game permit and allowance insufficient). Calls the REP token permit for the previewed amount from the caller to this game, ignores a failed permit when the existing allowance already covers that amount, then performs the depositRepOnOutcome deposit. REP Approval when the permit succeeds, then the depositRepOnOutcome signals
depositRepOnOutcomeWithAuthorization(owner, outcome, maximumDepositAttoRep, validAfter, validBefore, nonce, v, r, s) through fallback() Anyone relaying the owner's ERC-3009 signature The depositRepOnOutcome game, pool, and preview prerequisites; the pool universe is not genesis (Genesis REP does not support authorization); the signature authorizes the token nonce keccak256(abi.encode(nonce, operationHash, owner)), where operationHash is keccak256(abi.encode(depositRepOnOutcomeWithAuthorization.selector, owner, securityPool, universeId, questionId, outcome, maximumDepositAttoRep, previewedAmount)). Pulls the previewed amount from owner to this game through the REP token receiveWithAuthorization and records the deposit for owner. REP AuthorizationUsed and Transfer, LocalDepositAppended, DepositOnOutcome, EscalationSurplusAccrued when the ordinary minimum increases, and NonDecisionReached when the deposit reaches non-decision
recordDepositFromSecurityPool(depositor, outcome, amountAttoRep, expectedCumulativeAttoRep) Owning SecurityPool only (Only pool) Explicit non-decision state is None; game unresolved; valid outcome; preview and accepted cumulative amount match; room remains below threshold. Appends the nominal deposit and carry leaf. In ordinary games, it releases any increase in the minimum outcome balance through the same portfolio-income path as depositRepOnOutcome; only the new report’s retained contribution receives collateral credit. Continuations release no ordinary surplus. LocalDepositAppended, DepositOnOutcome, EscalationSurplusAccrued when the ordinary minimum increases, and NonDecisionReached when the deposit reaches non-decision
withdrawDeposit(depositIndex, outcome), the uint256 overload Owning SecurityPool only (Only pool) Explicit non-decision state is None; non-None supplied outcome; game final; game and pool final outcomes match; valid local deposit index, unsettled unless it is a retired ordinary loser. Settles one local deposit after resolution. An ordinary first claim freezes the winning liability and burns terminal excess beyond the surplus already paid at source; ordinary losers retire together and a valid losing index returns zero repeatedly. A winner consumes its reserved payout and burn and pays the immutable depositor. Continuation losers still consume their individual escrow. OrdinarySettlementInitialized on first ordinary settlement. Winners and continuation losers emit CarryDepositConsumed and VaultEscrowUpdated; winners also emit ClaimDeposit and positive payout or burn signals. Retired ordinary losers emit no per-deposit settlement event.
initializeForkCarryOutcome(sourceGame, snapshotId, peaks, leafCount, carryTotalAttoRep, resolutionBalanceAttoRep, nullifierRoot) Owning SecurityPool only Fork-continuation mode; fewer than three initialized outcomes; each leaf count fits the MMR; every call supplies the same source and nonzero snapshot ID, with the next outcome’s data. The third call requires the hash of all normalized data to match that ID. Installs one outcome’s inherited peaks, leaf count, carry total, resolution balance, and normalized nullifier root. The nonzero full snapshot identity and source are fixed on the first call. The third call verifies the installed data against that identity before marking the snapshot complete. Two or more threshold-full inherited balances then set nonDecisionState to InheritedThresholdTie without creating a local timestamp. ForkCarryCheckpoint after all three outcomes; additionally InheritedThresholdTie when the completed balances meet the non-decision threshold
processClaimCheckpoint(outcomeIndex, amountAttoRep, cumulativeAmountAttoRep, leafIndex, maxSteps, baseCommitment, transforms) through fallback() Anyone Complete fork snapshot when applicable; valid outcome and interval; maxSteps from 1 to 8 and no more transforms than that budget (Invalid checkpoint budget). An empty transform array requires a zero base commitment (Invalid checkpoint base). Discovery requires empty transforms (Checkpoint discovery pending) and each committed source to be PoolForked with its migration window closed. Applying queued transforms requires a nonempty batch no longer than the pending step count (Checkpoint transforms required), whose forward hash matches the pending commitment bound to this game and claim tuple (Invalid checkpoint batch); invalid or stale batches revert atomically. Completed calls and successful parent-cache adoption do not apply supplied transforms. Claims still require authenticated membership and an unspent nullifier. An empty transform array with a zero base commitment discovers at most eight frozen ancestor transforms per call and commits them to a hash stack. A completed canonical ancestor checkpoint for the same claim tuple replaces its already-prepared prefix; the excluded source transform is still processed. After discovery, a batch supplies one base commitment and at most eight transforms in forward hash order. The complete batch must hash to the pending commitment before those transforms apply in reverse order, preserving every generation’s integer rounding. Each transform contains repBeforeAttoRep, repRemainingAttoRep, and consumedBeforeAttoRep. Recovery anchors store a source and prior hash for each eight-transform segment. Every unfinished call checks the immediate parent’s completed cache; if available, it replaces even partially applied preparation with that prefix plus its one frozen excluded-source transform. Otherwise initialization reads the immediate source. The target and immediate parent remain live reads. Preparation does not consume a proof or move REP; completed calls are idempotent. ClaimCheckpointProgress; returns whether the stored checkpoint is complete. Read getClaimCheckpointProgress for readiness and remaining traversal state
initializeForkClaimCheckpoint(sourceGame) through fallback() Owning SecurityPool only (Only pool) sourceGame equals the source game recorded by the installed carry snapshot (Claim source). Records the root claim source game: the value sourceGame reports from rootClaimSourceGame(), or sourceGame itself when that value is zero. The game runs the same step internally while installing a carry snapshot with a nonzero source game, and no pool function calls this selector. No event
claimDepositForWinning(depositIndex, outcome) Owning SecurityPool or its SecurityPoolForker Non-None supplied outcome and valid unsettled local deposit with sufficient escrow. An ordinary non-fork game requires final settlement and the actual winning outcome. Other paths rely on the trusted caller to select the winner. Consumes a selected local deposit as a winner, consumes its vault escrow, burns the computed escalation haircut when nonzero, and transfers the remaining positive REP payout to the deposit's immutable depositor. CarryDepositConsumed, VaultEscrowUpdated, ClaimDeposit with transferredRep = true; REP payout Transfer and escalation-haircut burn signals only when their amounts are positive
exportUnresolvedDeposit(depositIndex, outcome) Owning SecurityPool or its SecurityPoolForker Non-None outcome and a valid unsettled local deposit. Ordinary settlement must not have initialized (Final claims not exportable); final resolution is not otherwise required. Returns deposit identity and amount to the trusted caller while consuming the local deposit from unresolved/escrow accounting without transferring REP. CarryDepositConsumed and VaultEscrowUpdated; no ClaimDeposit or REP transfer
withdrawDeposit(proof, outcome), the CarriedDepositProof overload Owning SecurityPool or its SecurityPoolForker Non-None supplied outcome; game final and matching the pool final outcome; supplied outcome is the winner; parent deposit was not directly claimed; valid unconsumed Merkle/nullifier proof. Consumes an inherited proof, transfers any positive winning payout, and burns the positive escalation haircut unless the fork already paid it. CarryDepositConsumed and ClaimDeposit with transferredRep = true; REP payout Transfer and escalation-haircut burn signals only when positive
exportVaultUnresolvedTotalsWithoutTransfer(vault) Owning SecurityPool or its SecurityPoolForker vault is nonzero and has not exported before; ordinary settlement has not initialized (Final claims not exportable). Marks the vault's local unresolved totals exported exactly once, clears each outcome amount, and consumes aggregate unresolved and escrow accounting when positive, but leaves token movement to its caller. Always VaultUnresolvedTotalsExported with transferredRep = false, including when every amount is zero; VaultEscrowUpdated only for a positive total; no REP transfer
drainAllRep(receiver) Owning SecurityPool only Noncentral custody and a nonzero receiver. Unreachable through current portfolio question adapters. Noncentral-custody helper that transfers the game REP balance. The portfolio-only protocol has no caller; central reporter custody rejects this operation. REP Transfer for a positive balance; no event at zero balance
recordForkedEscrowForOutcome(depositor, outcome, sourcePrincipalAttoRep, childRepAmountAttoRep) Owning SecurityPool or its SecurityPoolForker Outcome is not None; depositor is nonzero. Source principal and child REP may independently be zero; when both are zero, the call is a no-op. Accumulates source principal and child REP escrow for the depositor and outcome. The depositor remains the immutable payout owner; inherited claims remain in the carry commitment and are not copied into child-local ownership state. When both amounts are zero, returns without changing state or emitting an event. ForkedEscrowRecorded for a nonzero record; no event when both amounts are zero
exportForkedEscrowByOutcome(vault, repReceiver) Owning SecurityPool or its SecurityPoolForker vault and repReceiver are nonzero. Marks every remaining per-outcome escrow amount exported and transfers its positive child REP. When all outcomes were already empty or exported, returns zero arrays without state change, token transfer, or event. ForkedEscrowExported when any source principal or child REP remains; VaultEscrowUpdated and REP Transfer when positive child REP is transferred; no event for an already-empty export
exportForkedEscrowByOutcomeWithoutTransfer(vault) Owning SecurityPool or its SecurityPoolForker vault is nonzero. Marks every remaining per-outcome escrow amount exported without transferring child REP. When all outcomes were already empty or exported, returns zero arrays without state change or event. ForkedEscrowExported with transferredRep = false when any source principal or child REP remains; VaultEscrowUpdated when positive child REP remains; no REP transfer; no event for an already-empty export
settleOrdinaryGame() Anyone Ordinary game, not a fork continuation, with nonDecisionState = None and a final outcome. Game REP must cover the initial winner reserve (Winner reserve underfunded). Freezes the final outcome and effective fork threshold, reserves the cumulative winning payout and burn liability, and retires all losing local escrow without visiting deposits. Each later winning claim subtracts its payout and burn from that reserve. Burns terminal REP above the reserve; the ordinary minimum-outcome surplus was already paid irrevocably as deposits arrived. A repeated call with no surplus succeeds. See reporter liability invariant. OrdinarySettlementInitialized once; OrdinaryResidualRepBurned and REP Transfer only when surplus is positive
sweepResidualRepToSecurityPool() Anyone Final outcome and positive releasable surplus (No sweepable REP for an ordinary no-op). Ordinary settlement preserves all unclaimed winning liabilities. Continuations require no effective unresolved principal and, after retiring inherited aggregate escrow, no remaining local stake or vault escrow. Applies ordinary winner-reserve settlement and burns its terminal excess. Also burns fork-continuation residual so pre-child capital cannot accrue to late or nonexistent child owners. OrdinarySettlementInitialized if first ordinary settlement, then OrdinaryResidualRepBurned; ForkContinuationResidualRepBurned for a fork continuation

Accounting examples

Required support threshold

The contract waits ACTIVATION_DELAY (3 days) after start() before the escalation clock begins. From day 3 the cumulative binding-capital requirement rises from the configured start bond S to the non-decision threshold T over the 49-day ESCALATION_TIME_LENGTH, reaching T on day 52. The contract evaluates a fixed-point curve; this expression is its readable idealization.

A(d)=0for0≤d≤3=S×exp(ln(TS)×d−349)for3<d<52=Tford≥52

Winning-deposit payout

Binding capital is the median outcome balance at settlement; no outcome balance can exceed the non-decision threshold. The reward-eligible cap is binding capital plus binding capital divided by EXCESS_REWARD_WINDOW_DIVISOR (2), so only the portion of winning deposits up to 1.5 × binding capital participates in the bonus. Of the binding capital, 3 / 5 funds the reward pool and 2 / 5 funds the escalation-haircut pool; both are shared pro rata across the reward-eligible principal, which is the smaller of the winning outcome balance and that cap.

Let binding capital be 10 REP, so the reward-eligible cap is 15 REP, the reward pool is 6 REP, and the escalation-haircut pool is 4 REP. If the winning outcome holds 15 REP and one deposit contributed 5 REP inside the eligible range:

A winning deposit position above 15 REP returns its principal without a bonus. When Zoltar's fork threshold at settlement is below the game's non-decision threshold, the whole withdrawal is scaled by their ratio. If this game's non-decision threshold were 20 REP and the fork threshold 16 REP, the 7 REP payout becomes 7 × 16 / 20 = 5.6 REP, rounded down to attoREP. Fork scaling can therefore reduce the final transfer below principal.