# Statoblast Operator Reference

Operators, indexers, reviewers, and UI maintainers consult this reference for
contract-accurate guardrails, launch procedures, and edge-case behavior in one
subsystem at a time. The whitepapers carry the full protocol story.

Each section answers a different operational question: how the immutable launch
posture constrains releases, what a security pool or escalation game will and
will not accept, how fork migration behaves, how auction settlement works, and
how the REP/ETH coordinator stages or recovers operations.

Implementation guardrails map to their contract sources so operators can check
each rule against the exact Solidity implementation.

The [Protocol Invariants](./invariants.html) catalog connects those local
guardrails to cross-contract conservation, lifecycle, liveness, and economic
security properties, including launch-critical properties that the current
contracts do not preserve.

The [Protocol Security Model](./security-model.html) is normative for the
protocol's external assumptions.

## Security Review Orientation

Before classifying an economic or liveness concern, use the security model's
[grouped assumptions](./security-model.html) to identify external dependencies,
then follow its canonical mechanics links. The invariant catalog
owns the current requirement, status, and evidence for
[`EXT-05` recursive-fork gas behavior](./invariants.html#ext-05).

Operator work relies particularly on
[A23 verified deployments](./security-model.html#assumption-a23),
[A06 lifecycle executors](./security-model.html#assumption-a06),
[A20 chain-data and proof availability](./security-model.html#assumption-a20),
[A26 Ethereum execution and finality](./security-model.html#assumption-a26),
[A27 cryptographic security](./security-model.html#assumption-a27),
[A15 intended question selection](./security-model.html#assumption-a15),
[A25 safe immutable parameters](./security-model.html#assumption-a25),
[A22 asset-recipient compatibility](./security-model.html#assumption-a22),
[A24 client, RPC, and wallet integrity](./security-model.html#assumption-a24),
and
[A28 account authority](./security-model.html#assumption-a28).

## Assumption Monitoring

The security model is the canonical definition of each boundary. This table
assigns operational evidence and response for assumptions whose truth can change
with market or service conditions. Evaluate each signal at the same lineage,
pool, timestamp, numeraire, and decision horizon as the protected action.

| Assumptions | Operational evidence | Review cadence | Response when the boundary is weak or unknown |
| --- | --- | --- | --- |
| A01, A02, A03, A06 | Expected reward after gas, fees, delay, and capital lockup; number and independence of active liquidators, escalation participants, bidders, correctors, and transition executors; settle-ready OpenOracle reports, callback-recovery candidates, and overflow operations | Continuously for deadline-bearing flows; before launch and after parameter or gas-regime changes | Fund or arrange independent executors, reduce exposed value, or disclose that the affected transition may stall |
| A05, A07, A09, A11 | Parent and supported-child lineage value in one numeraire; observed user, custodian, exchange, interface, and proof-tool readiness to migrate assets and state within the applicable windows; documented continued-use value and secured value | Before a fork-security claim and throughout migration and coordination windows | Do not claim fork deterrence, practical migration, or value concentration; narrow supported lineage and exposure |
| A08, A13, A14 | REP supply basis, price source, depth and price impact; REP discounted-cash-flow methodology; protocol-accounted ETH collateral or explicitly broader open interest | At launch, continuously while open interest exists, and after material price, supply, liquidity, or exposure changes | Cap or stop new exposure in clients and disclosures; do not describe REP backing as economically sufficient |
| A04, A10 | Outcome evidence sources and availability; immediately mobilizable REP and transaction budget before each local-escalation deadline | From question creation through local resolution and any fork window | Mark the market or action impaired, surface the deadline, and avoid asserting that honest local correction remains fundable |
| A12 | Auction demand, indicative REP/ETH depth, expected discount, and bidder operating cost | Before and during every repair auction | Disclose likely under-repair and plan operation of the child at only migrated collateral plus accepted auction ETH |
| A16, A26 | Inclusion delay, base fee, priority fee, reorg depth, block gas limit, and gas schedule against each immutable window and mandatory transition | Continuously while a deadline or mandatory transition is live | Raise transaction fees where rational, use independent submission paths, and disclose missed-deadline or stranded-transition risk |
| A17, A18, A19 | Independent corrector availability, ownership and payoff independence, scenario-dependent WETH and REP replacement capital, reference-market depth, manipulation cost, correction profit after fees/gas/impact, transaction budget, and settlement inclusion | Continuously while a report is pending or a cached price can authorize operations | Block or discourage new price-sensitive operations and disclose that an incorrect report may settle |
| A21, A22 | Mainnet external-token code and behavior; Sepolia reviewed Genesis REP/WETH runtime bytecode, constructor allocations, and wiring; WETH redeemability; burn-sink status; recipient ETH/ERC-1155 compatibility | At deployment verification and before first use of a new recipient or integration | Reject the deployment or incompatible recipient; do not rely on redirected recovery |
| A20, A23, A24, A27, A28 | Pinned compiler and toolchain identity; reproducible-build output, reviewed bytecode hashes, release manifest, deployed runtime code and wiring; independent reorg-aware RPC/event replay; hash and CREATE2 verification; signer, typed-data domain, nonce, witness, session, and approval inventory | At release, on every environment or account change, and continuously for indexers | Stop signing or operating, reject an unverifiable deployment, revoke compromised authority where possible, and re-establish canonical state from independent sources |
| A15 | Immutable question ID and metadata, evidence plan, and pool relevance | Before pool selection | Reject or warn on the selection; do not represent an admitted question as relevant or resolvable |
| A25 | Deployed immutable values and every documented economic, timing, integer-width, and gas relationship | Before deployment and after any change in external gas or market conditions used by the model | Treat the immutable deployment as unsupported; there is no administrative parameter repair |

## Immutable Protocol Release Posture

Zoltar and Statoblast are intended to launch as immutable, permissionless
contracts. Launch documentation should not assume an operator can pause,
upgrade, roll back, or disable protocol behavior after deployment. Release work
should instead publish verifiable provenance: final commit and tag,
deterministic addresses, CI and local QA results, production UI artifact hash,
and any known limitations. UI deployments may describe data freshness and route
users to verified artifacts, but they must not be documented as emergency
controls over the protocol.
This is the protocol's
[EG05 no-pause, upgrade, rollback, or rescue boundary](./security-model.html#excluded-guarantee-eg05).

## Launch Release Checklist

Before tagging a launch release, run `bun run ui:build:prod` from a fresh
dependency install and run `bun run check:mainnet-deployment`. This command
fails when either generated deployment manifest is stale. Refresh and review
both manifests with `bun ./scripts/check-mainnet-deployment.mts --write` before
rerunning the check.
That command writes and checks both
[`mainnet-deployment-addresses.json`](../mainnet-deployment-addresses.json) and
[`sepolia-deployment-addresses.json`](../sepolia-deployment-addresses.json).
Use the pinned compiler configuration in
[`solidity/ts/compile.ts`](../../solidity/ts/compile.ts), the exact tool versions in
[`solidity/package.json`](../../solidity/package.json), and the imported OpenOracle
profile in
[`UPSTREAM.md`](../../solidity/contracts/peripherals/openOracle/UPSTREAM.md).
Publish the reproducible-build runtime hashes with the release, keyed to the
manifest addresses, and compare both a clean local rebuild and deployed runtime
code with those reviewed hashes before marking the release canonical.
Push the final `v*` tag only after the CI Gate succeeds on the same commit. The `Build and Push to IPFS` workflow must
succeed for that tag, and the resulting GitHub release must record the IPFS hash
emitted from the published artifact.

Production UI release notes should state that `?simulate=1` is a browser-local
sandbox. Mainnet and Sepolia quote-dependent actions use live RPC data plus
available network-local Uniswap liquidity, while simulation uses its configured
mock where supported. The
[OpenOracle integration guide](../protocol-design/open-oracle-integration.html#openoracle-role)
owns the quote-source order and network-address details. RPC and client
integrity remain covered by
[A24](./security-model.html#assumption-a24), while quote availability and
representativeness are official-client limitations rather than protocol
security assumptions. Stale, unavailable, or unsupported quotes are production
blockers for the affected client action, not inputs that should be replaced
with simulation prices.

## Genesis REP Deployment

Sepolia genesis REP allocations are canonical source data in
[`shared/ts/sepoliaRepAllocations.ts`](../../shared/ts/sepoliaRepAllocations.ts).
The listed holders and 10 million REP amount per holder are the intended
starting allocations for this release. Each amount string is denominated in REP
and `parseUnits(value, 18)` converts it once into atomic units. Review both the
REP input values and the computed bigint total before deployment.
The `GenesisReputationToken` constructor requires at least one allocation,
matching holder and balance array lengths, unique nonzero holders, and nonzero
balances. It emits the standard ERC-20 mint `Transfer` event once for each
allocation.

The sum of the constructor balances is immutable and is returned by
`getTotalTheoreticalSupply()`. There is no administrator, post-deployment mint,
allocation correction, or recovery entrypoint. An incorrect allocation must be
fixed in the source list before deployment and the deterministic manifests must
then be regenerated. Because constructor arguments are part of CREATE2 init
code, any allocation change produces a new genesis REP address and new
addresses for every deployment step whose constructor wiring depends on it.
Never continue a deployment from a manifest generated for a different
allocation list. A future release that intentionally changes starting holders
must follow the same source review and full-manifest regeneration procedure.

## Security Pool Guardrails

Pool creation, minting, withdrawal, and direct-ETH rules are collected here in
contract-first form. Participant-controlled payout and share-receiving addresses
must satisfy
[A22 asset-recipient compatibility](./security-model.html#assumption-a22).
Deterministic identity depends on
[A27 cryptographic security](./security-model.html#assumption-a27), while vault
and token authority depends on
[A28 account authority](./security-model.html#assumption-a28).

| Area | Implementation behavior | Source |
| --- | --- | --- |
| Origin pool shape | Origin pools require an existing question, an unforked universe, a present universe REP token, and exactly two categorical labels in this order: `Yes`, then `No`. Statoblast adds `Invalid` as the third trading and resolution outcome. The factory's configured escalation bond must be at least 1 REP, and a new origin requires its live non-decision threshold to exceed that configured bond. | [SecurityPoolFactory.sol](../../solidity/contracts/peripherals/factories/SecurityPoolFactory.sol), [ShareToken.sol](../../solidity/contracts/peripherals/tokens/ShareToken.sol), [BinaryOutcomes.sol](../../solidity/contracts/peripherals/BinaryOutcomes.sol) |
| Deployment history | The factory records security-pool deployments and exposes paged deployment-history reads for indexers and UIs. | [SecurityPoolFactory.sol](../../solidity/contracts/peripherals/factories/SecurityPoolFactory.sol) |
| Deterministic addresses | `SecurityPoolFactory` derives `securityPoolSalt = keccak256(abi.encode(parent, universeId, questionId, statoblastSecurityMultiplierBps, initialReportPriorityFeeWeiPerGas))`, using a zero parent for an origin. The coordinator and child truth-auction factories each hash that value again with their caller (`SecurityPoolFactory`) for their CREATE2 salt. The pool deployment worker instead uses literal CREATE2 salt zero; its address varies through the full constructor init-code hash, which contains the pool wiring. An origin share token uses `originId = keccak256(abi.encode(questionId, statoblastSecurityMultiplierBps, initialReportPriorityFeeWeiPerGas, originUniverseId))` directly as its CREATE2 salt, while factory ownership, Zoltar, and question ID remain in its init code; children reuse that lineage token and inherit its priority fee. | [SecurityPoolFactory.sol](../../solidity/contracts/peripherals/factories/SecurityPoolFactory.sol), [SecurityPoolDeployer.sol](../../solidity/contracts/peripherals/factories/SecurityPoolDeployer.sol), [PriceOracleManagerAndOperatorQueuerFactory.sol](../../solidity/contracts/peripherals/factories/PriceOracleManagerAndOperatorQueuerFactory.sol), [UniformPriceDualCapBatchAuctionFactory.sol](../../solidity/contracts/peripherals/factories/UniformPriceDualCapBatchAuctionFactory.sol), [ShareTokenFactory.sol](../../solidity/contracts/peripherals/factories/ShareTokenFactory.sol) |
| Share-token salt squatting | Direct `ShareTokenFactory` callers cannot reserve the canonical origin-pool share-token address. `CREATE2` includes constructor arguments in the init-code hash, and the share token owner is `msg.sender`, so a direct caller using the canonical salt deploys a caller-owned token at a different address than the `SecurityPoolFactory` deployment. | [ShareTokenFactory.sol](../../solidity/contracts/peripherals/factories/ShareTokenFactory.sol), [ShareToken.sol](../../solidity/contracts/peripherals/tokens/ShareToken.sol) |
| Complete-set capacity | Complete-set minting checks the next collateral amount against vault-assigned, fee-eligible bond capacity before minting shares. Vault allowance changes also cannot reduce that assigned capacity below existing collateral. Allowance reserved for an unclaimed truth-auction result cannot secure open interest until settlement attaches it to a vault. The pool updates accounting before the share-token mint call. | [`SecurityPool.createCompleteSet`](../../solidity/contracts/peripherals/SecurityPool.sol), [`SecurityPool.performSetSecurityBondsAllowance`](../../solidity/contracts/peripherals/SecurityPool.sol) |
| Fee accrual clamp | Fee accrual is clamped to the question end time while the universe is unforked; after a universe fork, the accumulator is clamped to the fork time. | [SecurityPool.sol](../../solidity/contracts/peripherals/SecurityPool.sol) |
| Fee accrual and rounding | Only vault-assigned allowance is fee-eligible. Collateral decay first enters an unallocated reserve; vault checkpoints preserve fractional carry and move only whole, redeemable wei into `totalFeesOwedToVaults`. `totalAccruedFees()` combines reserve and assigned debt for collateral reconciliation. Global fee-index and sub-wei carries preserve value between accruals, while allowance-scoped index carry is cleared when allowance ownership changes so old-denominator dust is not reassigned. After a fork permanently ends accrual, the pool tracks allowance still awaiting the final index; once every eligible vault checkpoints, any whole reserve wei that no vault can individually claim returns to collateral. | [`SecurityPool.updateCollateralAmount`](../../solidity/contracts/peripherals/SecurityPool.sol), [`SecurityPool.updateVaultFees`](../../solidity/contracts/peripherals/SecurityPool.sol), [`SecurityPool._clearFeeIndexRemainder`](../../solidity/contracts/peripherals/SecurityPool.sol) |
| Retention-rate updates | Retention-rate updates no-op when the pool is not `Operational`; otherwise utilization uses only vault-assigned, fee-eligible allowance, with zero eligible allowance selecting the maximum retention rate. | [SecurityPool.sol](../../solidity/contracts/peripherals/SecurityPool.sol) |
| Multiplier-preserving REP outflows | `performWithdrawRep` rejects withdrawal while the vault still has REP escrowed in an escalation game. Withdrawals and new escalation deposits independently preserve multiplier-adjusted REP backing for the affected vault and aggregate pool at the latest valid REP/ETH price. | [SecurityPool.sol](../../solidity/contracts/peripherals/SecurityPool.sol) |
| 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) |
| 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) |
| 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 multiplier-adjusted backing, transfers REP into the game, and records the deposit. The game factory normally preserves the configured bond; if later REP burns reduce the live threshold to that bond or below, it uses `nonDecisionThreshold - 1` so long as the threshold exceeds one atomic REP unit. | [`SecurityPool.depositToEscalationGame`](../../solidity/contracts/peripherals/SecurityPool.sol), [`EscalationGameFactory.deployEscalationGame`](../../solidity/contracts/peripherals/factories/EscalationGameFactory.sol), [`EscalationGame.recordDepositFromSecurityPool`](../../solidity/contracts/peripherals/EscalationGame.sol) |
| 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) |
| 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) |

## Share Migration

Security assumptions:
[A09 truthful-branch preference](./security-model.html#assumption-a09),
[A11 practical migration](./security-model.html#assumption-a11),
[A16 timely inclusion](./security-model.html#assumption-a16),
[A06 lifecycle executors](./security-model.html#assumption-a06), and
[A22 asset-recipient compatibility](./security-model.html#assumption-a22).

Share migration after a fork is user-facing asset migration, not vault REP
migration. Canonical rules live in [`FORK-10`](./invariants.html#fork-10) for
persistent per-child materialization, [`SHARE-04`](./invariants.html#share-04) for
the economic-claim denominator, and [`FORK-11`](./invariants.html#fork-11) for
unequal materialized supplies.

| Area | Implementation behavior | Source |
| --- | --- | --- |
| Persistent entitlement | `ShareToken.migrate` preserves the caller's parent token balance as a branch-independent entitlement. After its first use that source balance is transfer-locked, preventing a seller and buyer from materializing the same claim. | [ShareToken.sol](../../solidity/contracts/peripherals/tokens/ShareToken.sol) |
| Target list | The target outcome list must be non-empty, valid for the fork question, and strictly increasing. | [ShareToken.sol](../../solidity/contracts/peripherals/tokens/ShareToken.sol) |
| Canonical source and fork transition | Migration requires a canonical source pool for the token's universe. If that pool is still `Operational`, `migrate` first asks its forker to initiate the pool fork; the call proceeds only after the source is `PoolForked`. That conditional transition can freeze the source pool and emit the ordinary pool-fork and snapshot events. | [`ShareToken.migrate`](../../solidity/contracts/peripherals/tokens/ShareToken.sol), [`SecurityPoolForker.initiateSecurityPoolFork`](../../solidity/contracts/peripherals/SecurityPoolForker.sol) |
| Canonical destinations | Every destination must be a canonical direct child of the source pool. A single-target migration may lazily create a missing child while the branch-creation window is open; a multi-target migration requires every canonical child pool to exist before the call. Lazy creation can also emit child-link, REP-migration, and continuation events. | [`ShareToken.migrate`](../../solidity/contracts/peripherals/tokens/ShareToken.sol), [`SecurityPoolForker.createChildUniverse`](../../solidity/contracts/peripherals/SecurityPoolForker.sol) |
| Independent materialization | Each selected child token id is minted up to the current source balance. A later call can select another existing child, and source shares added through an ancestor migration materialize only their previously unminted delta. | [ShareToken.sol](../../solidity/contracts/peripherals/tokens/ShareToken.sol) |
| Economic denominator | Child setup copies the frozen parent's remaining economic claim supply rather than its currently materialized ERC-1155 supply. Complete-set minting and redemption update that denominator; share migration does not because its claims were reserved at fork time. | [SecurityPoolForker.sol](../../solidity/contracts/peripherals/SecurityPoolForker.sol), [SecurityPool.sol](../../solidity/contracts/peripherals/SecurityPool.sol) |
| Timing | The eight-week window still bounds child creation and vault/REP migration. Shares can materialize indefinitely in an already-created child. | [ShareToken.sol](../../solidity/contracts/peripherals/tokens/ShareToken.sol), [SecurityPoolForkerVaultMigrationBase.sol](../../solidity/contracts/peripherals/SecurityPoolForkerVaultMigrationBase.sol) |
| Malformed outcomes | Malformed fork outcomes are rejected using Zoltar question-data validation. | [ZoltarQuestionData.sol](../../solidity/contracts/ZoltarQuestionData.sol) |

## Escalation Resolution and Deposits

Security assumptions:
[A02 viable operating costs](./security-model.html#assumption-a02),
[A10 timely outcome evidence](./security-model.html#assumption-a10),
[A03 independent participants](./security-model.html#assumption-a03),
[A04 early alarm capital](./security-model.html#assumption-a04),
[A13 REP liquidity](./security-model.html#assumption-a13),
[A16 timely inclusion](./security-model.html#assumption-a16).

Accepted deposits, edge-case resolution results, and carry-proof or residual-REP
consumption all live in this section.

| Area | Implementation behavior | Source |
| --- | --- | --- |
| Deposit preview | The preview path expects a proposed amount of at least the current `startBond`. | [`EscalationGame.previewDepositOnOutcome`](../../solidity/contracts/peripherals/EscalationGame.sol) |
| Recorded deposit amount | The recorded deposit must be positive, and the accepted amount must be at least `startBond` unless it exactly fills the selected outcome to `nonDecisionThreshold`. | [`EscalationGame.recordDepositFromSecurityPool`](../../solidity/contracts/peripherals/EscalationGame.sol), [`EscalationGameCalculations._getAcceptedDepositAmount`](../../solidity/contracts/peripherals/EscalationGameCalculations.sol) |
| Outcome room | Accepted deposit amount is capped to the selected outcome's remaining room under `nonDecisionThreshold`. | [`EscalationGameCalculations._getAcceptedDepositAmount`](../../solidity/contracts/peripherals/EscalationGameCalculations.sol) |
| 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) |
| Unresolved resolution state | If two or more outcomes meet the current running cost, `getQuestionResolution()` returns `None`. | [`EscalationGameCalculations.getQuestionResolution`](../../solidity/contracts/peripherals/EscalationGameCalculations.sol) |
| 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) |
| 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) |
| 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) |
| 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 `⌈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) |
| `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) |
| `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) |
| `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) |
| 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) |
| 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) |
| Optional parent-lock cleanup | The public `SecurityPoolForker.migrateVaultWithUnresolvedEscalation` wrapper first runs ordinary migration for that same vault, which may move its unlocked ownership, allowance, fees, and collateral to the selected child. Its fixed-size escalation cleanup then exports one `Invalid`/`Yes`/`No` principal tuple without another token transfer. The cleanup preserves proof leaves and neither funds escalation backing nor authorizes inherited claims. | [`SecurityPoolForker.migrateVaultWithUnresolvedEscalation`](../../solidity/contracts/peripherals/SecurityPoolForker.sol), [`EscalationGameEscrow.exportVaultUnresolvedTotalsWithoutTransfer`](../../solidity/contracts/peripherals/EscalationGameEscrow.sol), [`EscalationGameForker.migrateVaultWithUnresolvedEscalation`](../../solidity/contracts/peripherals/EscalationGameForker.sol) |
| Residual sweep | Once a game is final, unresolved principal is cleared, and no escrow remains, residual REP in the escalation game can be swept back to the security pool. | [`EscalationGameSettlement.sweepResidualRepToSecurityPool`](../../solidity/contracts/peripherals/EscalationGameSettlement.sol) |

## Fork Migration

Security assumptions:
[A07 fork value preservation](./security-model.html#assumption-a07),
[A09 truthful-branch preference](./security-model.html#assumption-a09),
[A11 practical migration](./security-model.html#assumption-a11),
[A05 lineage access value](./security-model.html#assumption-a05),
[A21 genesis REP and WETH behavior](./security-model.html#assumption-a21),
[A06 lifecycle executors](./security-model.html#assumption-a06),
[A20 chain-data availability](./security-model.html#assumption-a20).

Pool-level migration mechanics after a universe fork live here: proxies,
child-pool creation, REP splitting, and child outcome selection.

| Area | Implementation behavior | Source |
| --- | --- | --- |
| Pool-specific migration identity | The forker lazily deploys one deterministic `SecurityPoolMigrationProxy` per parent pool. The proxy is the stable `msg.sender` for Zoltar migration accounting. REP sent to its predictable address before deployment remains isolated surplus: fork accounting uses newly routed REP and the Zoltar migration ledger, not the proxy’s preexisting ERC-20 balance. | [SecurityPoolForker.sol](../../solidity/contracts/peripherals/SecurityPoolForker.sol), [SecurityPoolMigrationProxy.sol](../../solidity/contracts/peripherals/SecurityPoolMigrationProxy.sol) |
| Proxy authority | The migration proxy is owner-controlled by the forker and wraps `lockRep`, `forkUniverse`, `splitToChild`, and child REP sweeping. | [SecurityPoolMigrationProxy.sol](../../solidity/contracts/peripherals/SecurityPoolMigrationProxy.sol) |
| Child REP backing | During vault migration, the forker ensures the child pool is backed by enough child-universe REP for cumulative migrated REP credited to that child. | [SecurityPoolForkerVaultMigrationBase.sol](../../solidity/contracts/peripherals/SecurityPoolForkerVaultMigrationBase.sol) |
| Vault fees during migration | Migration uses one fixed, fee-exclusive snapshot and a cumulative REP ceiling. The parent vault is checkpointed before its allowance is cleared, so earned fees remain redeemable, and parent-to-child ETH transfers cannot consume the balance reserved by `totalAccruedFees()`. The [Fork Migration Proportion](../whitepapers/statoblast-whitepaper.html#eq-statoblast-fork-migration-proportion) and [Fork Collateral Ceiling](../whitepapers/statoblast-whitepaper.html#eq-statoblast-fork-collateral-ceiling) own checkpoint order, cumulative allocation, and repair derivation. | [SecurityPoolForker.sol](../../solidity/contracts/peripherals/SecurityPoolForker.sol), [SecurityPoolForkerVaultMigrationBase.sol](../../solidity/contracts/peripherals/SecurityPoolForkerVaultMigrationBase.sol), [SecurityPool.sol](../../solidity/contracts/peripherals/SecurityPool.sol) |
| Split shortfall tracking | The forker tracks how much REP has already been split for each parent-pool/outcome pair and only splits the shortfall before sweeping child REP into the child pool. | [SecurityPoolForkerVaultMigrationBase.sol](../../solidity/contracts/peripherals/SecurityPoolForkerVaultMigrationBase.sol) |
| Canonical continuation snapshot | Fork initialization stores the complete parent `Invalid`/`Yes`/`No` balances, carry totals, peaks, leaf counts, and nullifier roots once. Every lazily created child reads that same stored snapshot, even if an allowed parent claim occurs before a later child is created. | [`SecurityPoolForker._snapshotEscalationAtFork`](../../solidity/contracts/peripherals/SecurityPoolForker.sol), [`SecurityPoolForkerBase._initializeChildForkedEscalationGameIfNeeded`](../../solidity/contracts/peripherals/SecurityPoolForkerBase.sol), [`EscalationGameCarry.initializeForkCarrySnapshotWithResolutionBalances`](../../solidity/contracts/peripherals/EscalationGameCarry.sol) |
| Aggregate escalation backing | An external unrelated fork reproduces the drained game's escalation REP one-for-one in each selected child. The escalation's own fork transfers post-haircut aggregate backing instead; ordinary pool REP remains one-to-one. Each selected child receives its applicable aggregate backing once, and `resumeFromFork` remains paused until that backing is present after accounting for child REP already exported by valid direct pre-resume claims. See the canonical [fork-migration derivation](../whitepapers/statoblast-whitepaper.html#migration) and [`FORK-08`](./invariants.html#fork-08) for the raw and effective principal definitions and exact funding bound. Neither path scales or releases per-vault child escrow. | [`SecurityPoolForker.initiateSecurityPoolFork`](../../solidity/contracts/peripherals/SecurityPoolForker.sol), [`SecurityPoolForker.forkZoltarWithOwnEscalationGame`](../../solidity/contracts/peripherals/SecurityPoolForker.sol), [`SecurityPoolForkerVaultMigrationBase._ensureChildEscalationBacking`](../../solidity/contracts/peripherals/SecurityPoolForkerVaultMigrationBase.sol), [`EscalationGame.resumeFromFork`](../../solidity/contracts/peripherals/EscalationGame.sol) |
| Direct-claim replay protection | A successful direct own-fork claim records both the stable parent deposit identity and cumulative claimed principal by outcome. Every current, late, or recursively inherited child rejects a second payout; effective inherited principal subtracts immediate-parent direct claims so those leaves cannot strand the residual sweep. | [`EscalationGameForker.claimForkedEscalationDeposits`](../../solidity/contracts/peripherals/EscalationGameForker.sol), [`SecurityPoolForker.isEscalationDepositClaimedDirectly`](../../solidity/contracts/peripherals/SecurityPoolForker.sol), [`EscalationGameCarry._getEffectiveInheritedUnresolvedTotal`](../../solidity/contracts/peripherals/EscalationGameCarry.sol) |
| Optional vault cleanup | See [Optional parent-lock cleanup](#escalation-resolution-and-deposits) for wrapper ordering and proof independence. In migration terms, the call records cleanup for one selected child and never processes another vault. | [`SecurityPoolForker.migrateVaultWithUnresolvedEscalation`](../../solidity/contracts/peripherals/SecurityPoolForker.sol), [`EscalationGameForker.migrateVaultWithUnresolvedEscalation`](../../solidity/contracts/peripherals/EscalationGameForker.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) |
| Own-fork REP buckets | When escalation triggers its own fork, `escalationChildRepAtFork` equals `escalationRepToFork - ⌊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) |
| 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) |
| 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](../whitepapers/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) |
| 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) |

## Truth Auction Operations

Security assumptions:
[A01 bidder incentives](./security-model.html#assumption-a01),
[A02 viable operating costs](./security-model.html#assumption-a02),
[A03 independent bidders](./security-model.html#assumption-a03),
[A12 efficient REP conversion](./security-model.html#assumption-a12),
[A06 lifecycle executors](./security-model.html#assumption-a06),
[A20 bid-data availability](./security-model.html#assumption-a20),
[A25 safe immutable parameters](./security-model.html#assumption-a25), and
[A22 native-ETH recipient compatibility](./security-model.html#assumption-a22).

Collateral-repair auctions have three operator-critical boundaries: forker
ownership, a one-week bidding window, and paged settlement into vault
accounting. Bids close at <code>auctionStarted + AUCTION_TIME</code>; direct
auction finalization is allowed at <code>&gt;=</code> that boundary, but the
public forker wrapper requires the boundary to have passed. The canonical
clearing rules and examples are in [Truth Auction](../protocol-design/truth-auction.html#clearing).

| Area | Implementation behavior | Source |
| --- | --- | --- |
| Owner | Child-pool truth auctions are owned by `SecurityPoolForker`. The direct auction `startAuction` and `finalize` calls are owner-only, while anyone can reach them through `startTruthAuction` and `finalizeTruthAuction`. | [UniformPriceDualCapBatchAuction.sol](../../solidity/contracts/peripherals/UniformPriceDualCapBatchAuction.sol), [SecurityPoolForker.sol](../../solidity/contracts/peripherals/SecurityPoolForker.sol) |
| Finalized settlement | After finalization, only the auction owner withdraws bid outcomes from the auction; `SecurityPoolForker` wraps that call so anyone can settle a vault's bid pages. | [UniformPriceDualCapBatchAuction.sol](../../solidity/contracts/peripherals/UniformPriceDualCapBatchAuction.sol), [SecurityPoolForker.sol](../../solidity/contracts/peripherals/SecurityPoolForker.sol) |
| Child fee activation | Completed migration or truth-auction settlement starts a new child fee epoch. Only vault-assigned allowance accrues; each claimed auction allowance joins incrementally at the current fee index. A delayed claim adds to the pool’s live eligible total, so allowance changes or liquidations since activation are preserved rather than replaced by fork-time counters. | [SecurityPool.sol](../../solidity/contracts/peripherals/SecurityPool.sol), [SecurityPoolForker.sol](../../solidity/contracts/peripherals/SecurityPoolForker.sol) |

## REP/ETH Oracle Operations

Security assumptions:
[A01 arbitrage incentives](./security-model.html#assumption-a01),
[A13 REP liquidity](./security-model.html#assumption-a13),
[A16 timely inclusion](./security-model.html#assumption-a16),
[A17 corrector capability](./security-model.html#assumption-a17),
[A18 independent correction incentive](./security-model.html#assumption-a18),
[A19 observable correctable price](./security-model.html#assumption-a19),
[A06 lifecycle executors](./security-model.html#assumption-a06),
and
[A22 native-ETH recipient compatibility](./security-model.html#assumption-a22).

The coordinator quick reference below covers staging, callback recovery,
stale-operation handling, and liquidation boundaries. Report sizing, request
cost, and current OpenOracle parameters are canonical in
[OpenOracle Integration](../protocol-design/open-oracle-integration.html#parameters).

| Area | Implementation behavior | Source |
| --- | --- | --- |
| Atomic initial report | The sponsor funds the ETH bounty and WETH/REP position; the coordinator submits that position atomically as the initial reporter. A caller-selected WETH amount above the dynamic minimum is allowed. See [OpenOracle sizing and funding](../protocol-design/open-oracle-integration.html#security-guarantee) for derivation, reporter withdrawals, application buffering, and escalation effects. | [OpenOraclePriceCoordinator.sol](../../solidity/contracts/peripherals/OpenOraclePriceCoordinator.sol), [openOracle.ts](../../ui/ts/protocol/openOracle.ts) |
| Immediate execution | If a price is still valid, the operation executes immediately and positive unused ETH is refunded. A contract caller must accept the refund callback or the execution rolls back; the [canonical refund warning](../protocol-design/open-oracle-integration.html#refund-callback) also covers newly opened reports. | [OpenOraclePriceCoordinator.sol](../../solidity/contracts/peripherals/OpenOraclePriceCoordinator.sol) |
| Fresh-price request guard | `requestPrice` reverts while the cached coordinator price is still valid, so callers cannot open a redundant pending report on top of a fresh cache. | [OpenOraclePriceCoordinator.sol](../../solidity/contracts/peripherals/OpenOraclePriceCoordinator.sol) |
| Staging guardrails | Withdraw and liquidation amounts must be non-zero; allowance updates may set zero. Validity must be positive and no more than five minutes. Non-liquidation operations must target the caller's own vault. Liquidation must target a different vault; same-vault liquidation is rejected with `Caller bad` before oracle request or execution. | [OpenOraclePriceCoordinator.sol](../../solidity/contracts/peripherals/OpenOraclePriceCoordinator.sol) |
| Pending report bound | At most four operations are attached to one settlement callback. Operations can still be tracked as active even when they do not fit into the pending callback batch. | [OpenOraclePriceCoordinator.sol](../../solidity/contracts/peripherals/OpenOraclePriceCoordinator.sol) |
| Sponsor exclusivity | Once the cached price is stale and a caller funds a fresh coordinator report, only that `pendingReportSponsor` can append more staged operations until settlement. Valid disputes reset the settlement clock, so this paid exclusive lane can be extended indefinitely; the coordinator makes no bounded-availability guarantee. The [economic tradeoffs](../protocol-design/open-oracle-integration.html#intentional-economic-tradeoffs), [attack model](../protocol-design/open-oracle-integration.html#attack-model), and [parameter table](../protocol-design/open-oracle-integration.html#parameters) own dispute funding, escalation, and rounding details. | [OpenOraclePriceCoordinator.sol](../../solidity/contracts/peripherals/OpenOraclePriceCoordinator.sol), [OpenOracle.sol](../../solidity/contracts/peripherals/openOracle/OpenOracle.sol) |
| High settlement basefee | The callback clears the pending report but no-ops if settlement basefee is above the stored maximum multiplier from request time. | [OpenOraclePriceCoordinator.sol](../../solidity/contracts/peripherals/OpenOraclePriceCoordinator.sol) |
| Uneconomic or saturated final report | Coordinator reports always enable dispute history. The callback reads `storedGame(reportId).numReports`. It rejects a saturated `uint24` counter with `Counter saturated`; otherwise it requires the final history record's WETH amount to cover the configured dispute-security formula at its recorded base fee plus the configured priority fee and rejects it with `Report uneconomic`. | [OpenOraclePriceCoordinator.sol](../../solidity/contracts/peripherals/OpenOraclePriceCoordinator.sol), [OpenOracle.sol](../../solidity/contracts/peripherals/openOracle/OpenOracle.sol) |
| Zero report values | A callback with zero amount, zero denominator, or a computed zero price does not update `lastPrice`. | [OpenOraclePriceCoordinator.sol](../../solidity/contracts/peripherals/OpenOraclePriceCoordinator.sol) |
| Recovery path | Coordinator reports opt into OpenOracle's `STORE_ALL` and `TRACK_DISPUTES` flags. `recoverSettledPendingReport` requires both a pending report and a nonzero `storedGame(reportId).settlementTimestamp`; it returns the coordinator's withdrawable reporter balances to the sponsor, clears the report, and consumes the associated pending operation slot. | [OpenOraclePriceCoordinator.sol](../../solidity/contracts/peripherals/OpenOraclePriceCoordinator.sol) |
| Consumed failures | Expired operations, stale liquidations, zero-effect withdrawals, and liquidations too close to threshold are consumed and emitted as failed executions rather than retried forever. | [OpenOraclePriceCoordinator.sol](../../solidity/contracts/peripherals/OpenOraclePriceCoordinator.sol) |
| Liquidation snapshot | A staged liquidation becomes stale if target ownership decreases or target allowance changes. A target vault can deposit more REP without making the queued snapshot stale, but a large enough top-up can still make execution fail `No gain` when the final full-close sweep would no longer improve target health. | [OpenOraclePriceCoordinator.sol](../../solidity/contracts/peripherals/OpenOraclePriceCoordinator.sol), [SecurityPool.sol](../../solidity/contracts/peripherals/SecurityPool.sol) |
| Liquidation distance | A staged liquidation must remain at least `minLiquidationPriceDistanceBps` beyond the liquidation threshold when it executes. | [OpenOraclePriceCoordinator.sol](../../solidity/contracts/peripherals/OpenOraclePriceCoordinator.sol) |

## Support Module Inventory

The whitepapers focus on protocol flow. The table below names the remaining
support contracts that matter for integrators, code reviewers, and interface
inventory work.

### Caller and trust boundaries

Deployment helpers are not interchangeable with canonical protocol discovery. Several are intentionally permissionless and namespace `CREATE2` salts by `msg.sender`; an application must discover canonical instances through `SecurityPoolFactory`, recognized pools, and recognized forker events rather than treating every factory-created address as canonical.

| Module | Direct caller boundary | Canonical-use boundary |
| --- | --- | --- |
| `EscalationGameFactory` | `deployEscalationGame` and `deployEscalationGameFromFork` have no permission check, but a successful caller must implement the `ISecurityPool` reads used during construction; an EOA or incompatible contract reverts. The caller is bound into the new game as its `securityPool`; the factory itself becomes the game's immutable `owner` and immediately calls `start` or `startFromFork`. Ordinary deployment requires a threshold above one atomic REP unit and lowers a start bond at or above that threshold to `threshold - 1`. The factory has no owner role and no later `resumeFromFork` relay. | Accept a game only after `EscalationGameSet` from a recognized pool. In the supported continuation path, the owning pool calls `resumeFromFork`, which also verifies aggregate funding. |
| `ShareTokenFactory` | Anyone can call `deployShareToken` to deploy or retrieve a token under `keccak256(abi.encode(msg.sender, salt, questionId))`; that caller is the token's initial authorized address. | Origin lineage tokens are the instances created by `SecurityPoolFactory` and named in `DeploySecurityPool`; children reuse the parent's token. |
| `UniformPriceDualCapBatchAuctionFactory` | Anyone can call `deployUniformPriceDualCapBatchAuction`. Its salt is namespaced by caller and supplied salt, and its operational owner is the caller-supplied `owner` address. | During external-universe initiation, the source must be authorized by its declared share token; own-game initiation does not perform that check, and neither relationship proves configured-factory registration. Child linking requires a deployed auction that this forker has never trusted before and preserves the source's factory and forker. Canonical pools remain the instances registered by the configured `SecurityPoolFactory`. |
| `PriceOracleManagerAndOperatorQueuerFactory` | Anyone can call `deployPriceOracleManagerAndOperatorQueuer` under a caller-namespaced salt with caller-supplied OpenOracle, REP token, and positive `initialReportPriorityFeeWeiPerGas`; coordinator construction rejects zero and values that would consume the reserved OpenOracle `uint128` report and escalation-halt capacity. The caller therefore chooses this immutable gas-price assumption within that bound. | A pool coordinator is the instance named by canonical `DeploySecurityPool`; `SecurityPoolFactory` atomically binds it to that pool before returning, and canonical child deployment inherits the value from the parent coordinator. |
| `SecurityPoolDeployer` and `SecurityPoolDeploymentWorker` | Only the configured `SecurityPoolFactory` may call the deployer; only that deployer may call its worker. | They are code-size deployment plumbing. Pools become canonical only when the factory emits `SecurityPoolRegistered` and `DeploySecurityPool`. |
| `SecurityPoolMigrationProxy` | Only its immutable `owner`, the `SecurityPoolForker` that created it, may call `lockRep`, `forkUniverse`, `splitToChild`, or `sweepChildRep`. | Its deterministic per-parent address is exposed by `getMigrationProxyAddress` and recorded in fork snapshot events; users do not call it. |
| `EscalationGameDepositDelegate`, `EscalationGameForker`, and `SecurityPoolForkerVaultMigrationDelegate` | Their public methods are delegatecall implementations: `recordDeposit` for a game; `claimForkedEscalationDeposits` and `migrateVaultWithUnresolvedEscalation` for a forker; and `createChildUniverse`, `migrateVault`, `ensureChildPoolRepSplit`, and `finalizeTruthAuctionRepair` for a forker. Direct calls operate on the helper's own uninitialized or isolated storage and are not protocol actions. | Accept resulting state and logs only when the recognized game or forker executes the matching wrapper through `delegatecall`. |
| [`SecurityPoolEventEmitter.sol`](../../solidity/contracts/peripherals/SecurityPoolEventEmitter.sol) | `emitPoolAccountingCheckpoint`, `emitVaultAccountingCheckpoint`, and `emitForkSnapshotEvents` are externally callable and `payable`, but direct calls execute against the helper's own storage and emit from the helper address. Payability permits delegatecalls from value-bearing protocol flows; callers must not send ETH directly because it is not protocol collateral and the helper has no recovery surface. | Pools and the forker use constructor- or factory-installed modules through `delegatecall`, so logs are emitted from the recognized pool or forker address. Indexers must reject matching signatures from the helper or any unrecognized emitter. External-universe fork initiation requires declared-share-token authorization; own-game initiation does not. Child linking preserves the source factory and forker and rejects undeployed or previously trusted auctions. Configured-factory registration remains the canonicality boundary. Storage-layout tests protect the delegate's fixed slots. |
| `EscalationGameProofVerifier`, `MerkleMountainRange`, and `SecurityPoolUtils` | Stateless or library math and proof routines have no lifecycle authority. Public verifier calls can be used for previews, but do not mutate a game or pool. | A result becomes protocol state only through a recognized game, pool, or forker transaction and its events. |
| `DeploymentStatusOracle` | Anyone can call `getDeploymentMask`; the constructor alone fixes the ordered address list and emits `DeploymentAddressesSet`. | It reports code presence only, not canonical wiring or readiness. Decode it using its constructor event or the matching deployment manifest order. |

| Area | Named contracts and modules | Role |
| --- | --- | --- |
| Deployment tracking | [`DeploymentStatusOracle.sol`](../../solidity/contracts/DeploymentStatusOracle.sol) | Reports one code-presence bit per configured deployment-step address. See [Deployment Status Oracle](../architecture-deployment/deployment-status.html). |
| Carry proof hashing | [`MerkleMountainRange.sol`](../../solidity/contracts/peripherals/MerkleMountainRange.sol), [`EscalationGameProofVerifier.sol`](../../solidity/contracts/peripherals/EscalationGameProofVerifier.sol), [`EscalationGameTypes.sol`](../../solidity/contracts/peripherals/EscalationGameTypes.sol) | Defines the carried-deposit leaf shape, the 64-peak limit, proof-length rules, and nullifier-root replay protection. See [Merkle Mountain Range carry proofs](../architecture-deployment/merkle-mountain-range.html). |
| Escalation game composition | [`EscalationGame.sol`](../../solidity/contracts/peripherals/EscalationGame.sol), [`EscalationGameCalculations.sol`](../../solidity/contracts/peripherals/EscalationGameCalculations.sol), [`EscalationGameCarry.sol`](../../solidity/contracts/peripherals/EscalationGameCarry.sol), [`EscalationGameDepositDelegate.sol`](../../solidity/contracts/peripherals/EscalationGameDepositDelegate.sol), [`EscalationGameEscrow.sol`](../../solidity/contracts/peripherals/EscalationGameEscrow.sol), [`EscalationGameSettlement.sol`](../../solidity/contracts/peripherals/EscalationGameSettlement.sol), [`EscalationGameState.sol`](../../solidity/contracts/peripherals/EscalationGameState.sol), [`EscalationGameStorage.sol`](../../solidity/contracts/peripherals/EscalationGameStorage.sol) | Splits the game across immutable ownership and storage, deposit delegation, calculations, continuation proofs, escrow, and settlement without exposing those internal modules as separate canonical games. |
| ERC-20 support | [`ERC20.sol`](../../solidity/contracts/ERC20.sol), [`IERC20.sol`](../../solidity/contracts/IERC20.sol), [`IERC20Metadata.sol`](../../solidity/contracts/IERC20Metadata.sol), [`Context.sol`](../../solidity/contracts/Context.sol), [`SafeERC20Ops.sol`](../../solidity/contracts/SafeERC20Ops.sol), [`GenesisReputationToken.sol`](../../solidity/contracts/GenesisReputationToken.sol), [`ReputationToken.sol`](../../solidity/contracts/ReputationToken.sol) | Base REP token implementation, interfaces, metadata, execution context, safe transfer wrappers, the constructor-allocated genesis token with fixed theoretical supply, and the inherited `transfer`, `approve`, and `transferFrom` entrypoints. |
| ERC-1155 and token ids | [`ERC1155.sol`](../../solidity/contracts/peripherals/tokens/ERC1155.sol), [`ShareToken.sol`](../../solidity/contracts/peripherals/tokens/ShareToken.sol), [`TokenId.sol`](../../solidity/contracts/peripherals/tokens/TokenId.sol), [`IERC1155.sol`](../../solidity/contracts/peripherals/interfaces/IERC1155.sol), [`IERC1155Receiver.sol`](../../solidity/contracts/peripherals/interfaces/IERC1155Receiver.sol), [`IERC165.sol`](../../solidity/contracts/peripherals/interfaces/IERC165.sol), [`IShareToken.sol`](../../solidity/contracts/peripherals/interfaces/IShareToken.sol) | Outcome-share token plumbing, interface support, token-id encoding, inherited `setApprovalForAll`, and both single and batch `safeTransferFrom` forms. |
| Factories and deployers | [`EscalationGameFactory.sol`](../../solidity/contracts/peripherals/factories/EscalationGameFactory.sol), [`SecurityPoolFactory.sol`](../../solidity/contracts/peripherals/factories/SecurityPoolFactory.sol), [`SecurityPoolDeployer.sol`](../../solidity/contracts/peripherals/factories/SecurityPoolDeployer.sol), [`ShareTokenFactory.sol`](../../solidity/contracts/peripherals/factories/ShareTokenFactory.sol), [`UniformPriceDualCapBatchAuctionFactory.sol`](../../solidity/contracts/peripherals/factories/UniformPriceDualCapBatchAuctionFactory.sol), [`PriceOracleManagerAndOperatorQueuerFactory.sol`](../../solidity/contracts/peripherals/factories/PriceOracleManagerAndOperatorQueuerFactory.sol) | Deterministic deployment entrypoints for pool, share-token, oracle-coordinator, escalation-game, and auction instances. |
| Migration delegates and storage modules | [`SecurityPoolMigrationProxy.sol`](../../solidity/contracts/peripherals/SecurityPoolMigrationProxy.sol), [`SecurityPoolForker.sol`](../../solidity/contracts/peripherals/SecurityPoolForker.sol), [`SecurityPoolForkerAuctionSettlementBase.sol`](../../solidity/contracts/peripherals/SecurityPoolForkerAuctionSettlementBase.sol), [`SecurityPoolForkerBase.sol`](../../solidity/contracts/peripherals/SecurityPoolForkerBase.sol), [`SecurityPoolForkerStorage.sol`](../../solidity/contracts/peripherals/SecurityPoolForkerStorage.sol), [`SecurityPoolForkerTypes.sol`](../../solidity/contracts/peripherals/SecurityPoolForkerTypes.sol), [`SecurityPoolForkerVaultMigrationBase.sol`](../../solidity/contracts/peripherals/SecurityPoolForkerVaultMigrationBase.sol), [`SecurityPoolForkerVaultMigrationDelegate.sol`](../../solidity/contracts/peripherals/SecurityPoolForkerVaultMigrationDelegate.sol), [`EscalationGameForker.sol`](../../solidity/contracts/peripherals/EscalationGameForker.sol), [`SecurityPoolEventEmitter.sol`](../../solidity/contracts/peripherals/SecurityPoolEventEmitter.sol) | Split fork-time state, truth-auction settlement, vault and unresolved-escalation migration execution, event encoding, and stable proxy identity used while routing parent state into child pools. |
| Protocol interfaces | [`IEscalationGame.sol`](../../solidity/contracts/peripherals/interfaces/IEscalationGame.sol), [`ISecurityPool.sol`](../../solidity/contracts/peripherals/interfaces/ISecurityPool.sol), [`ISecurityPoolForker.sol`](../../solidity/contracts/peripherals/interfaces/ISecurityPoolForker.sol), [`ISecurityPoolForkerChildEscalationGameInitializer.sol`](../../solidity/contracts/peripherals/interfaces/ISecurityPoolForkerChildEscalationGameInitializer.sol), [`IUniformPriceDualCapBatchAuction.sol`](../../solidity/contracts/peripherals/interfaces/IUniformPriceDualCapBatchAuction.sol), [`IWeth9.sol`](../../solidity/contracts/peripherals/interfaces/IWeth9.sol), [`IAugur.sol`](../../solidity/contracts/peripherals/interfaces/IAugur.sol) | Typed boundaries used by games, pools, migration delegates, auctions, WETH integration, and external Augur compatibility. |
| Protocol utilities | [`Constants.sol`](../../solidity/contracts/Constants.sol), [`ScalarOutcomes.sol`](../../solidity/contracts/ScalarOutcomes.sol), [`BinaryOutcomes.sol`](../../solidity/contracts/peripherals/BinaryOutcomes.sol), [`SecurityPoolUtils.sol`](../../solidity/contracts/peripherals/SecurityPoolUtils.sol), [`Multicall3.sol`](../../solidity/contracts/peripherals/Multicall3.sol), [`WETH9.sol`](../../solidity/contracts/peripherals/WETH9.sol) | Shared constants and math, outcome representations, Multicall3 `aggregate`, `tryAggregate`, `tryBlockAndAggregate`, `blockAndAggregate`, `aggregate3`, `aggregate3Value`, and block-context reads, plus standard WETH9 `deposit`, `withdraw`, approval, and transfer support. |
| Imported oracle integration | [`UPSTREAM.md`](../../solidity/contracts/peripherals/openOracle/UPSTREAM.md), [`OpenOracle.sol`](../../solidity/contracts/peripherals/openOracle/OpenOracle.sol), [`Errors.sol`](../../solidity/contracts/peripherals/openOracle/libraries/Errors.sol), [`ISignatureTransfer.sol`](../../solidity/contracts/peripherals/openOracle/interfaces/ISignatureTransfer.sol), [`interfaces/IERC20.sol`](../../solidity/contracts/peripherals/openOracle/openzeppelin/contracts/interfaces/IERC20.sol), [`interfaces/IERC165.sol`](../../solidity/contracts/peripherals/openOracle/openzeppelin/contracts/interfaces/IERC165.sol), [`token/ERC20/IERC20.sol`](../../solidity/contracts/peripherals/openOracle/openzeppelin/contracts/token/ERC20/IERC20.sol), [`IERC1363.sol`](../../solidity/contracts/peripherals/openOracle/openzeppelin/contracts/interfaces/IERC1363.sol), [`SafeERC20.sol`](../../solidity/contracts/peripherals/openOracle/openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol), [`Panic.sol`](../../solidity/contracts/peripherals/openOracle/openzeppelin/contracts/utils/Panic.sol), [`ReentrancyGuard.sol`](../../solidity/contracts/peripherals/openOracle/openzeppelin/contracts/utils/ReentrancyGuard.sol), [`StorageSlot.sol`](../../solidity/contracts/peripherals/openOracle/openzeppelin/contracts/utils/StorageSlot.sol), [`utils/introspection/IERC165.sol`](../../solidity/contracts/peripherals/openOracle/openzeppelin/contracts/utils/introspection/IERC165.sol), [`Math.sol`](../../solidity/contracts/peripherals/openOracle/openzeppelin/contracts/utils/math/Math.sol), [`SafeCast.sol`](../../solidity/contracts/peripherals/openOracle/openzeppelin/contracts/utils/math/SafeCast.sol) | OpenOracle's imported source, exact SlimStorage revision, compiler profile, and dependency provenance are owned by `UPSTREAM.md`. The coordinator submits atomic reports with dispute history and full game storage enabled; OpenOracle's packed event stream remains separate from Zoltar replay. |
