You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A branch selected by a matching fork becomes the immutable
415
-
continuation outcome, unrelated forks preserve the previous fixed
416
-
outcome, and escalation-deposit withdrawal rejects a pool/game
415
+
continuation outcome, later universe forks cannot transition that
416
+
fixed pool, and escalation-deposit withdrawal rejects a pool/game
417
417
mismatch.
418
418
</td>
419
419
</tr>
@@ -1748,16 +1748,21 @@ <h2>Escalation Games and Carried Claims</h2>
1748
1748
<divclass="invariant-property">
1749
1749
When a universe forks on a pool's question, each child pool and its
1750
1750
continuation game use that child's Invalid, Yes, or No branch as
1751
-
the final pool-question outcome. A later fork on the same question
1752
-
replaces the inherited outcome with its newly selected branch; a
1753
-
fork on another question preserves the inherited outcome. Deposit
1754
-
withdrawal reverts unless the pool and game report the same outcome.
1751
+
the final pool-question outcome. Once a pool inherits that fixed
1752
+
outcome, new local escalation deposits and every later fork
1753
+
transition revert, whether the new universe fork uses the same
1754
+
question or another one. Deposit withdrawal reverts unless the pool
1755
+
and game report the same outcome.
1755
1756
</div>
1756
-
<pclass="invariant-example"><strong>Example:</strong> A Yes child created by a fork on the pool question pays carried Yes deposits even if copied game balances favored No; a later unrelated fork keeps Yes as the payout outcome.</p>
1757
+
<pclass="invariant-example"><strong>Example:</strong> A Yes child created by a fork on the pool question pays carried Yes deposits even if copied game balances favored No. It rejects new local escalation REP before escrow, so a later local non-decision cannot lock vault redemption. A later matching or unrelated universe fork leaves the stored <code>SystemState.Operational</code> and fixed Yes outcome unchanged, and eligible share, vault REP, and carried-proof redemption paths remain available, while universe-fork guards still freeze normal operating calls.</p>
Copy file name to clipboardExpand all lines: docs/operator-reference.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -77,7 +77,7 @@ contract-first form.
77
77
| Escrowed REP withdrawal lock |`performWithdrawRep` rejects withdrawal while the vault still has REP escrowed in an escalation game; the vault must settle those locks first. |[SecurityPool.sol](../solidity/contracts/peripherals/SecurityPool.sol)|
78
78
| External fork withdrawal lock | If the universe forked before the local escalation game ended and non-decision was not reached, parent-pool escalation withdrawal reverts. The child continuation already has the canonical snapshot and aggregate backing: winning inherited deposits settle there by proof, inherited losers require no transaction, and clearing the vault's parent lock accounting is optional. |[SecurityPool.sol](../solidity/contracts/peripherals/SecurityPool.sol), [`EscalationGameSettlement.withdrawDeposit`](../solidity/contracts/peripherals/EscalationGameSettlement.sol), [`EscalationGameCarry._getEffectiveInheritedUnresolvedTotal`](../solidity/contracts/peripherals/EscalationGameCarry.sol)|
79
79
| REP-to-ownership round-up |`repToPoolOwnershipRoundUp` uses ceiling division when the pool removes vault ownership for an escalation deposit. That intentionally burns enough ownership to cover the requested REP even when the ownership conversion is fractional. |[`SecurityPool.repToPoolOwnershipRoundUp`](../solidity/contracts/peripherals/SecurityPool.sol), [`SecurityPool.depositToEscalationGame`](../solidity/contracts/peripherals/SecurityPool.sol)|
80
-
| Escalation deposit wrapper |`depositToEscalationGame` deploys the game on the first valid post-end deposit, previews the accepted amount, removes vault REP ownership with round-up accounting, checks local and global solvency, transfers REP into the game, and records the deposit. |[`SecurityPool.depositToEscalationGame`](../solidity/contracts/peripherals/SecurityPool.sol), [`EscalationGame.recordDepositFromSecurityPool`](../solidity/contracts/peripherals/EscalationGame.sol)|
80
+
| Escalation deposit wrapper |`depositToEscalationGame`rejects pools with an inherited fixed outcome because they cannot enter another fork or safely unwind a later local non-decision. Otherwise it deploys the game on the first valid post-end deposit, previews the accepted amount, removes vault REP ownership with round-up accounting, checks local and global solvency, transfers REP into the game, and records the deposit. |[`SecurityPool.depositToEscalationGame`](../solidity/contracts/peripherals/SecurityPool.sol), [`EscalationGame.recordDepositFromSecurityPool`](../solidity/contracts/peripherals/EscalationGame.sol)|
81
81
| Direct ETH receiver | Ordinary calls to `receive()` accept ETH only from the forker, its truth auction, or its parent pool. Forced ETH can bypass `receive()`; it remains raw, unaccounted surplus and is not collateral or accrued fees. |[SecurityPool.sol](../solidity/contracts/peripherals/SecurityPool.sol)|
82
82
| Vault enumeration |`getVaults(startIndex, count)` pages the append-only vault list in insertion order. `getActiveVaults(startIndex, count)` pages only active vaults in newest-first order by walking the active-vault linked list from `latestActiveVault`. Both return an empty array when `count == 0` or the start index is out of range. |[`SecurityPool.getVaults`](../solidity/contracts/peripherals/SecurityPool.sol), [`SecurityPool.getActiveVaults`](../solidity/contracts/peripherals/SecurityPool.sol)|
83
83
@@ -112,12 +112,12 @@ consumption all live in this section.
112
112
| Outcome room | Accepted deposit amount is capped to the selected outcome's remaining room under `nonDecisionThreshold`. |[`EscalationGameCalculations._getAcceptedDepositAmount`](../solidity/contracts/peripherals/EscalationGameCalculations.sol)|
113
113
| Tie adjustment | If the accepted amount would create a tie with the current maximum balance while still below non-decision, the contract reduces the accepted amount by `1 wei`; if that breaks the accepted-amount rule, the deposit is rejected. |[`EscalationGameCalculations._getAcceptedDepositAmount`](../solidity/contracts/peripherals/EscalationGameCalculations.sol)|
114
114
| Unresolved resolution state | If two or more outcomes meet the current running cost, `getQuestionResolution()` returns `None`. |[`EscalationGameCalculations.getQuestionResolution`](../solidity/contracts/peripherals/EscalationGameCalculations.sol)|
115
-
| Matching-fork continuation resolution |When a universe fork uses the pool's question, every child stores the selected branch as its fixed question outcome whether the fork began through the pool-specific or direct Zoltar entrypoint. After the continuation deadline, the game uses that same fixed outcome for deposit settlement; unrelated descendant forks inherit an existing fixed outcome, while unrelated forks of unresolved pools retain local continuation semantics. Payout settlement also rejects any pool/game outcome mismatch. |[`EscalationGameCalculations.getQuestionResolution`](../solidity/contracts/peripherals/EscalationGameCalculations.sol), [`EscalationGameSettlement._getPayoutQuestionResolution`](../solidity/contracts/peripherals/EscalationGameSettlement.sol), [`SecurityPoolForker.getQuestionOutcome`](../solidity/contracts/peripherals/SecurityPoolForker.sol)|
115
+
| Matching-fork continuation resolution | After the continuation deadline, a game with a fixed child outcome settles deposits against that outcome. Payout settlement rejects any pool/game outcome mismatch. See [Matching-question child outcome](#fork-migration) for the pool-level finality rule. |[`EscalationGameCalculations.getQuestionResolution`](../solidity/contracts/peripherals/EscalationGameCalculations.sol), [`EscalationGameSettlement._getPayoutQuestionResolution`](../solidity/contracts/peripherals/EscalationGameSettlement.sol), [`SecurityPoolForker.getQuestionOutcome`](../solidity/contracts/peripherals/SecurityPoolForker.sol)|
116
116
| Empty-game fallback | If all outcome balances are zero after the running cost is non-zero, `getQuestionResolution()` returns `Invalid`; if the running cost is still zero, the unresolved check returns `None` first. |[`EscalationGameCalculations.getQuestionResolution`](../solidity/contracts/peripherals/EscalationGameCalculations.sol)|
117
117
| Strict leading resolution | After the unresolved-cost check and the all-zero `Invalid` fallback, a strict `Invalid`, `Yes`, or `No` lead returns that outcome. Valid local deposits prevent tied maxima below non-decision by reducing the accepted amount by `1 wei`, or reverting if that adjusted amount becomes invalid. Continuation snapshots preserve the parent balances exactly, including ties, so every selected branch starts from the same unresolved game state. |[`EscalationGameCalculations.getQuestionResolution`](../solidity/contracts/peripherals/EscalationGameCalculations.sol), [`EscalationGameCalculations._getStrictLeaderOrNone`](../solidity/contracts/peripherals/EscalationGameCalculations.sol), [`EscalationGameCalculations._getAcceptedDepositAmount`](../solidity/contracts/peripherals/EscalationGameCalculations.sol), [`EscalationGameCarry.initializeForkCarrySnapshotWithResolutionBalances`](../solidity/contracts/peripherals/EscalationGameCarry.sol)|
118
118
| Structural non-decision predicate |`hasReachedNonDecision()` becomes true when two or more outcomes reach `nonDecisionThreshold`; `nonDecisionState` separately records how that balance condition entered the lifecycle. New games use `ceil(forkThreshold / 2)`, so two threshold balances always contain at least the REP required to fund an own fork even when the fork threshold is odd. |[`Zoltar.getNonDecisionThreshold`](../solidity/contracts/Zoltar.sol), [`EscalationGameCalculations.hasReachedNonDecision`](../solidity/contracts/peripherals/EscalationGameCalculations.sol)|
119
119
|`nonDecisionState = None`| No explicit non-decision transition has occurred. Deposits may remain available subject to the ordinary activation, continuation, timing, and amount guards. |[`EscalationGame.previewDepositOnOutcome`](../solidity/contracts/peripherals/EscalationGame.sol), [`EscalationGameDepositDelegate.recordDepositFromSecurityPool`](../solidity/contracts/peripherals/EscalationGameDepositDelegate.sol)|
120
-
|`nonDecisionState = Local`| A local deposit brought a second outcome to the threshold. The game stores the real `nonDecisionTimestamp`, closes further deposits, and `canTriggerOwnFork()` returns true. |[`EscalationGameDepositDelegate.recordDepositFromSecurityPool`](../solidity/contracts/peripherals/EscalationGameDepositDelegate.sol), [`EscalationGameCalculations.canTriggerOwnFork`](../solidity/contracts/peripherals/EscalationGameCalculations.sol)|
120
+
|`nonDecisionState = Local`| A local deposit brought a second outcome to the threshold. The game stores the real `nonDecisionTimestamp`, closes further deposits, and `canTriggerOwnFork()` returns true. That predicate is game-local: a pool with an inherited fixed outcome still rejects the fork transition in `activateForkMode()`. |[`EscalationGameDepositDelegate.recordDepositFromSecurityPool`](../solidity/contracts/peripherals/EscalationGameDepositDelegate.sol), [`EscalationGameCalculations.canTriggerOwnFork`](../solidity/contracts/peripherals/EscalationGameCalculations.sol), [`SecurityPool.activateForkMode`](../solidity/contracts/peripherals/SecurityPool.sol)|
121
121
|`nonDecisionState = InheritedThresholdTie`| Snapshot initialization preserved two or more threshold-full balances without fabricating a local timestamp. The game closes further deposits. With a fixed child outcome it follows the continuation clock and cannot trigger its own fork; without one, `canTriggerOwnFork()` returns true directly. |[`EscalationGameCarry.initializeForkCarrySnapshotWithResolutionBalances`](../solidity/contracts/peripherals/EscalationGameCarry.sol), [`EscalationGameCalculations.getEscalationGameEndDate`](../solidity/contracts/peripherals/EscalationGameCalculations.sol), [`EscalationGameCalculations.canTriggerOwnFork`](../solidity/contracts/peripherals/EscalationGameCalculations.sol)|
122
122
| Carry proofs | Inherited carry uses Merkle Mountain Range peaks and nullifier roots so child games can consume proofs without replaying already-spent parent deposits. |[`EscalationGameSettlement.withdrawDeposit`](../solidity/contracts/peripherals/EscalationGameSettlement.sol), [`EscalationGameCarry._verifyAndConsumeCarriedDepositProof`](../solidity/contracts/peripherals/EscalationGameCarry.sol)|
123
123
| Continuation withdrawal | Anyone may relay a batch of winning carried proofs for one beneficiary after a child continuation resolves. Each proof authenticates its recorded depositor, consumes that leaf once, and pays the depositor from aggregate game REP. Inherited losing outcomes retire in constant-size work when the result is final and require no proof transaction; locally created losing deposits retain ordinary settlement. |[`SecurityPool.withdrawForkedEscalationDeposits`](../solidity/contracts/peripherals/SecurityPool.sol), [`EscalationGameSettlement.withdrawDeposit`](../solidity/contracts/peripherals/EscalationGameSettlement.sol), [`EscalationGameCarry._getEffectiveInheritedUnresolvedTotal`](../solidity/contracts/peripherals/EscalationGameCarry.sol)|
| Independent continuation liveness | Child creation initializes the canonical carry and aggregate backing without waiting for vault transactions. Once final, authenticated winning proofs can be relayed permissionlessly, inherited losers retire without proofs, and optional parent cleanup may happen independently. |[`SecurityPoolForkerBase._finalizeAwaitingForkContinuationIfReady`](../solidity/contracts/peripherals/SecurityPoolForkerBase.sol), [`EscalationGameSettlement.withdrawDeposit`](../solidity/contracts/peripherals/EscalationGameSettlement.sol), [`EscalationGameCarry._getEffectiveInheritedUnresolvedTotal`](../solidity/contracts/peripherals/EscalationGameCarry.sol)|
144
144
| Own-fork REP buckets | When escalation triggers its own fork, `escalationChildRepAtFork` equals `escalationRepToFork - floor(forkThreshold / forkBurnDivisor)`. `vaultRepAtFork` preserves ordinary pool REP one-for-one. Creating one selected child does not reduce the post-haircut escalation backing available to another selected child. |[`SecurityPoolForker.forkZoltarWithOwnEscalationGame`](../solidity/contracts/peripherals/SecurityPoolForker.sol), [`SecurityPoolForker.getOwnForkRepBuckets`](../solidity/contracts/peripherals/SecurityPoolForker.sol), [`SecurityPoolForkerBase._initializeOwnForkRepBuckets`](../solidity/contracts/peripherals/SecurityPoolForkerBase.sol)|
145
145
| Child-pool deployment window | Child pools are created lazily for selected fork outcomes, but only while the parent pool is `PoolForked` and the eight-week migration window is still open. |[SecurityPoolForkerVaultMigrationBase.sol](../solidity/contracts/peripherals/SecurityPoolForkerVaultMigrationBase.sol), [SecurityPoolUtils.sol](../solidity/contracts/peripherals/SecurityPoolUtils.sol)|
146
-
| Matching-question child outcome | When the parent universe forks on the pool's question, the child stores its selected Zoltar outcome index as a fixed result whether the fork used the pool-specific path or a direct Zoltar call. The fixed result applies after continuation and is inherited through later unrelated descendants. `ownFork` changes accounting only. |[SecurityPoolForkerVaultMigrationBase.sol](../solidity/contracts/peripherals/SecurityPoolForkerVaultMigrationBase.sol), [SecurityPoolForker.sol](../solidity/contracts/peripherals/SecurityPoolForker.sol)|
146
+
| Matching-question child outcome | When the parent universe forks on the pool's question, the child stores its selected branch as a fixed result. `depositToEscalationGame` rejects new local deposits, and `activateForkMode` rejects every later pool fork transition. See [Child Outcome Resolution](./statoblast-whitepaper.html#child-outcome-resolution) for the collateral and REP-liveness rationale. |[SecurityPool.sol](../solidity/contracts/peripherals/SecurityPool.sol),[SecurityPoolForkerVaultMigrationBase.sol](../solidity/contracts/peripherals/SecurityPoolForkerVaultMigrationBase.sol), [SecurityPoolForker.sol](../solidity/contracts/peripherals/SecurityPoolForker.sol)|
147
147
| Unrelated-fork child outcome | A child created by an unrelated fork without an inherited fixed result uses a local escalation result only if that escalation ended before the universe forked; otherwise continuation or later state must produce the outcome. |[SecurityPoolForker.sol](../solidity/contracts/peripherals/SecurityPoolForker.sol)|
MIN_SECURITY_BOND_DEBT: 'The smallest security-bond debt amount tracked. Smaller dust amounts are avoided.',
119
119
minLiquidationPriceDistanceBps: 'The basis-point distance required beyond the liquidation threshold before execution.',
120
120
'non-decision threshold': 'The REP balance level that two or more outcomes must reach for the structural non-decision condition.',
121
-
'non-decision': 'A structurally contested escalation state. Whether it authorizes a fork depends on whether it arose locally or was inherited and, for an inherited tie, whether the continuation has a fixed outcome.',
121
+
'non-decision': "A structurally contested escalation state. Its local or inherited origin determines the game's canTriggerOwnFork() predicate, but a successful pool fork also requires no inherited fixed outcome. Fixed-outcome pools reject new local escalation deposits before this state can be created.",
122
122
NUM_OUTCOMES: 'The Statoblast constant for the three supported outcomes: Invalid, Yes, and No.',
123
123
NULLIFIER_DEPTH: 'The depth of the tree used to remember consumed proofs. It prevents the same carried deposit from being used twice.',
124
124
'number of ticks': 'The scalar-outcome denominator used to map a scalar answer onto payout numerators.',
0 commit comments