<!-- Generated by scripts/generate-contract-interaction-reference.mts. Do not edit directly. -->
<!-- Validated production Solidity source fingerprint: cde16e42c8cae575d597e85c5cf03ddae501ffc060f015d9c2fb3130d162a4fd -->
# Contract Interaction Reference

The main state-changing protocol calls map to caller authority, lifecycle prerequisites, effects, and observable events below. The conceptual flow begins in [Start Here](./start-here.html), while the [Operator Reference](./operator-reference.md) covers edge cases and the application build consumes the complete generated ABI.

The tables focus on transaction entrypoints in the ten primary state-changing contracts that users and protocol components interact with directly. Each read surface names every read-only function and public storage getter in the deployed contract ABI; its hidden fingerprint pins the exact source declarations, including parameters, returns, visibility, and mutability. Protocol-only rows identify calls that applications should observe but ordinary users should reach through the owning pool, forker, factory, or coordinator. Stateless helpers, deployment workers, factories used only for component construction, migration proxies, and event emitters are inventoried with their caller boundaries in the Operator Reference.

Failure behavior follows Solidity transaction semantics: an uncaught revert rolls back the transaction. The coordinator is the important exception at the workflow level because it deliberately consumes several failed staged operations and records the result in `ExecutedStagedOperation`.

## ZoltarQuestionData

Creates immutable, content-addressed scalar or categorical questions and exposes their display metadata. [Source](../solidity/contracts/ZoltarQuestionData.sol)

Read surface: Use `getQuestionId` before submission; `questionCreatedTimestamp`, `questions`, and `outcomeLabels` for direct lookup; `questionIds`, `getQuestionCount`, and `getQuestions` for indexed or paged discovery; and `getQuestionEndDate`, `getOutcomeLabels`, `splitUint256IntoTwoWithInvalid`, `hasNonZeroScalarReservedBits`, `isMalformedAnswerOption`, and `getAnswerOptionName` when validating or displaying answers.

<!-- Validated read ABI fingerprint: 5359875c236b41ea3d1b7af175b02ce8c7f00b5d5bf655869b7103ce363168df -->
<!-- Validated complete compiled ABI fingerprint: 5158fa721a2d0c38a3c04c8e2b0e4060904c33dfe65122f20028f13db2fdf4f7 -->

| Transaction | Caller | Main prerequisites | State or asset effect | Primary signals |
| --- | --- | --- | --- | --- |
| `createQuestion(questionData, outcomeOptions)` | Anyone | Question ID not already created; end time is on or after start time. Scalar questions use no labels, require display maximum greater than minimum, and positive ticks. Categorical questions require nonempty labels whose `keccak256(abi.encode(label))` values are strictly descending. | Stores the question at its deterministic content hash, records the creation timestamp, appends it to discovery order, and stores categorical labels when supplied. | `QuestionCreated` |

## Zoltar

Registers universe forks, charges the fork admission haircut, and mints branch-specific child REP. [Source](../solidity/contracts/Zoltar.sol)

Read surface: Use `universes`, `deployedChildOutcomeIndexes`, `forkThresholdDivisor`, `forkBurnDivisor`, `zoltarQuestionData`, `getForkTime`, `forkQuestionMatches`, `getRepToken`, `getForkThreshold`, `getNonDecisionThreshold`, `getUniverseTheoreticalSupply`, `getChildUniverseId`, `getDeployedChildUniverses`, and `getMigrationRepBalance` to reconstruct universe and migration state.

<!-- Validated read ABI fingerprint: 84e9d44350c2a27cc521f9525e34f385e810e0093aa0626ad64bcb490a925fe9 -->
<!-- Validated complete compiled ABI fingerprint: f7c46fef11823d944ae835cca01905b07e06e4396b834caf1c30fdd6736e2c87 -->

| Transaction | Caller | Main prerequisites | State or asset effect | Primary signals |
| --- | --- | --- | --- | --- |
| `forkUniverse(universeId, questionId)` | Any address able to fund the current fork threshold | Initialized and unforked universe; existing ended question; sufficient caller REP. Genesis REP requires allowance; child REP is burned directly without allowance. | Records the fork, removes threshold REP from the parent universe, and credits the caller with the threshold minus the configured uncredited haircut. | `UniverseForked` |
| `burnRep(universeId, amount)` | Any REP holder; the caller can burn only its own balance | Initialized universe; positive amount; sufficient caller REP and theoretical supply. Genesis REP requires allowance. | Permanently removes REP without creating migration credit; escalation settlement uses this when the haircut was not paid through its own fork. | `RepBurned` and the token burn or transfer event |
| `deployChild(universeId, outcomeIndex)` | Anyone | Parent forked; outcome is well formed; child is not already deployed. | Deploys the deterministic child REP token and initializes the child universe. | `DeployChild` |
| `addRepToMigrationBalance(universeId, amount)` | Parent REP holder | Universe forked; sufficient caller REP. Genesis REP requires allowance; child REP is burned directly without allowance. | Burns or sinks additional parent REP and increases the caller's reusable migration balance. | `MigrationRepAdded` |
| `splitMigrationRep(universeId, amount, outcomeIndexes)` | Migration-balance holder | Universe forked. A nonempty list additionally requires every outcome to be well formed and the cumulative amount per child not to exceed the caller's migration balance. | Mints `amount` of child REP into every selected branch, deploying missing children lazily. An empty outcome list returns after the universe-fork guard without outcome validation, deployment, minting, or events. A nonempty zero-amount call still validates every outcome, may deploy missing children, performs zero-value child REP mints, and records a zero split for every branch. | `TheoreticalSupplySet` and `DeployChild` when needed; child REP `Transfer` and `Mint`, then `MigrationRepSplit`, per selected branch, including at zero amount; no event for an empty list |

## ReputationToken

Implements universe-specific ERC-20 REP and enforces the supply ceiling maintained by Zoltar. [Source](../solidity/contracts/ReputationToken.sol)

Read surface: Use `getTotalTheoreticalSupply`, `zoltar`, and the standard ERC-20 `name`, `symbol`, `decimals`, `totalSupply`, `balanceOf`, and `allowance` reads.

<!-- Validated read ABI fingerprint: 16a3e564da0ed3bc8da54a65d8051e810d27f8f50db525f5f1d176301168efd7 -->
<!-- Validated complete compiled ABI fingerprint: a7c983224bd1738e3cf9300f139edfa6968519466c71d881c65242d2013ed6c1 -->

| Transaction | Caller | Main prerequisites | State or asset effect | Primary signals |
| --- | --- | --- | --- | --- |
| `setMaxTheoreticalSupply(totalTheoreticalSupply)` | `Zoltar` only | Called by Zoltar as part of child-universe creation. | Sets the child token theoretical-supply ceiling used to bound subsequent migration mints. | `TheoreticalSupplySet` |
| `mint(account, value)` | `Zoltar` only | `account` is nonzero; resulting ERC-20 supply does not exceed theoretical supply. | Mints branch REP to an account. | `Mint` and ERC-20 `Transfer` |
| `burn(account, value)` | `Zoltar` only | `account` is nonzero and has sufficient REP; theoretical supply covers the burn. | Burns account REP and reduces both actual and theoretical supply by the same amount. | `Burn` and ERC-20 `Transfer` |
| `transfer(to, value)` | REP holder | Destination is nonzero; caller has sufficient balance. | Moves REP from the caller without changing actual or theoretical supply. | `Transfer` |
| `approve(spender, value)` | Any REP account setting its own allowance | Spender is nonzero. | Replaces the named spender allowance without moving REP. | `Approval` |
| `transferFrom(from, to, value)` | A spender with sufficient allowance from `from` | Source and destination are nonzero; source has sufficient balance; caller has sufficient allowance, including when caller equals source. | Moves REP from `from`; a finite allowance decreases by `value`, while an infinite allowance remains unchanged. Neither allowance path emits `Approval`. | `Transfer` only |

## SecurityPoolFactory

Creates and canonically registers origin and child security pools with their share token, oracle coordinator, and optional truth auction. [Source](../solidity/contracts/peripherals/factories/SecurityPoolFactory.sol)

Read surface: Use `initialEscalationGameDeposit` for the immutable deployment parameter and `securityPoolDeploymentCount` with the strict `securityPoolDeploymentsRange(startIndex, count)` pager, which reverts rather than truncating when the requested range exceeds the array. Use `getOriginId`, `getPoolId`, `getSecurityPool`, `getSecurityPoolOriginId`, and `getSecurityPoolHasInheritedForkOutcome` for canonical lookup.

<!-- Validated read ABI fingerprint: 2a851398716178a195c1119681a111452b0cf421d177ddd0151b6d5bb8648396 -->
<!-- Validated complete compiled ABI fingerprint: 63f58449dfc5115e0e8e13d90498a9c0a8b9bea022260817bcd46329dd7e7998 -->

| Transaction | Caller | Main prerequisites | State or asset effect | Primary signals |
| --- | --- | --- | --- | --- |
| `deployOriginSecurityPool(universeId, questionId, securityMultiplier)` | Anyone | `securityMultiplier > 1`; question exists and has exactly the categorical labels `Yes`, then `No`; universe is unforked and has a REP token; the origin/universe slot has not already been claimed. | Creates the canonical origin pool, its lineage-wide share token, and its price coordinator, then wires and registers them atomically. | `SecurityPoolRegistered`, then `DeploySecurityPool` |
| `deployChildSecurityPool(parent, shareToken, universeId, questionId, securityMultiplier, currentRetentionRate, completeSetCollateralAmount)` | `SecurityPoolForker` only | Parent is the canonical pool for its lineage; supplied share token equals the parent share token; target origin/universe slot is unclaimed; deployment arguments satisfy downstream constructors and wiring. | Creates and registers a canonical child pool with a coordinator and forker-owned truth auction while retaining the parent lineage share token. | `SecurityPoolRegistered`, then `DeploySecurityPool` |

## SecurityPool

Holds ETH collateral and REP underwriting, accounts for vaults and fees, mints shares, and routes local escalation. [Source](../solidity/contracts/peripherals/SecurityPool.sol)

Read surface: Immutable relationship and configuration getters are `questionId`, `universeId`, `initialEscalationGameDeposit`, `zoltar`, `parent`, `shareToken`, `repToken`, `priceOracleManagerAndOperatorQueuer`, `openOracle`, `escalationGameFactory`, `questionData`, `securityPoolForker`, `truthAuction`, `securityPoolFactory`, and `securityMultiplier`; the current game is `escalationGame`. Accounting and lifecycle getters are `totalSecurityBondAllowance`, `completeSetCollateralAmount`, `poolOwnershipDenominator`, `shareTokenSupply`, `totalFeesOwedToVaults`, `lastUpdatedFeeAccumulator`, `feeIndex`, `currentRetentionRate`, `awaitingForkContinuation`, `securityVaults`, and `systemState`. Use `securityPoolEventEmitter`, `getVaultCount`, `getActiveVaultCount`, `getVaults`, `getActiveVaults`, `sharesToCash`, `cashToShares`, `repToPoolOwnership`, `repToPoolOwnershipRoundUp`, `poolOwnershipToRep`, `getTotalRepBalance`, `totalAccruedFees`, `getPoolAccountingSnapshot`, `getVaultFeeRemainder`, and `isEscalationResolved` for derived or paged state. `isEscalationResolved()` is true only when a local escalation game is configured and the forker routes a non-`None` outcome; an operational fixed-outcome child without a local game returns false. `SystemState` determines which transaction paths remain open.

<!-- Validated read ABI fingerprint: 06857683318415b32aa066f45f57ec80cd841048bb855f1ca4bd10f6ed723ae3 -->
<!-- Validated complete compiled ABI fingerprint: a89b8774585a67959e34124765e2ad1065eb3d2895a0a2fc38368cd14556d6b1 -->

| Transaction | Caller | Main prerequisites | State or asset effect | Primary signals |
| --- | --- | --- | --- | --- |
| `burnEscalationWinnerHaircut(amount)` | This pool's `EscalationGame` only | Caller is the configured escalation game; amount is positive and the game has already transferred enough REP to the pool. | Burns the winning-deposit haircut from REP already escrowed in the game. | `RepBurned` and ERC-20 `Transfer`; child REP also emits `Burn` |
| `depositRep(repAmount)` | Vault owner | Operational and unforked; `isEscalationResolved()` is false; resulting vault REP meets the minimum. | Transfers REP into the pool and credits proportional pool ownership. | `DepositRep` |
| `redeemFees(vault)` | Anyone; any nonzero ETH payment is always sent to `vault` | A nonzero payment path requires `vault` to accept ETH. | First accrues the vault's fees. If resulting unpaid fees are zero, returns without payment; otherwise clears and pays the full amount. | Accrual checkpoints only when accrual state changes; both `VaultAccountingCheckpoint` and `PoolAccountingCheckpoint` for a nonzero redemption; no event when fees and accrual state are unchanged |
| `createCompleteSet()` with ETH | Trader | Operational and unforked; `isEscalationResolved()` is false; not awaiting continuation; positive ETH converts to at least one complete-set unit; bond capacity covers the new collateral; a contract trader accepts `onERC1155BatchReceived`. | Adds collateral and mints one `Invalid`, `Yes`, and `No` share per complete-set unit, then invokes the ERC-1155 batch-receiver callback for a contract trader. Callback rejection rolls back the ETH, pool accounting, events, and share mint. | `CompleteSetCreated`, `PoolAccountingCheckpoint`, then ERC-1155 `TransferBatch` on a successful callback |
| `redeemCompleteSet(completeSetAmount)` | Anyone; positive redemption requires the caller to hold the complete set | Operational and unforked; caller owns every outcome amount requested; caller accepts the resulting ETH call, including zero value. Zero is accepted without a token balance. | Burns equal balances of all three outcomes and pays `completeSetAmount * completeSetCollateralAmount / shareTokenSupply` using the pool's remaining economic claim supply as its collateral denominator. Complete-set issuance adds to that denominator, while complete-set and winning-share redemption consume it; fork-time source entitlements materialize without changing it because their claims are already reserved. Zero passes the token and accounting checks and follows the normal zero-value event, checkpoint, and ETH-send path; rejection of that ETH call reverts the transaction. | `CompleteSetRedeemed` and `PoolAccountingCheckpoint` |
| `redeemShares()` | Anyone; a positive payout requires the caller to hold winning shares | Operational pool with a final outcome; caller accepts the resulting ETH call, including zero value. | Burns the caller's full winning balance and pays its pro-rata remaining collateral. A zero winning balance passes token and accounting checks and follows the normal zero-value event, checkpoint, and ETH-send path; rejection of that ETH call reverts the transaction. | `SharesRedeemed` and `PoolAccountingCheckpoint` |
| `redeemRep(vault)` | Anyone; REP is always sent to `vault` | Operational pool with a final outcome; the specified `vault` has no escalation escrow and has redeemable REP. | Burns the vault's pool-ownership claim and returns its proportional REP. | `RedeemRep` |
| `depositToEscalationGame(outcome, maxAmount)` | Vault owner | Question end has passed; pool operational in an unforked universe, without an inherited fixed outcome, and not awaiting continuation; outcome and amount accepted; remaining vault and pool backing stay solvent; fresh price when allowance is nonzero. | Deploys the local game on the first deposit, removes enough vault ownership, and escrows accepted REP on the selected outcome. | `EscalationGameSet` on first deposit; `DepositToEscalationGame` |
| `withdrawFromEscalationGame(outcome, depositIndexes)` | Anyone; a nonempty list must select deposits belonging to one beneficiary vault | Game configured; operational pool; valid final outcome. If an external fork interrupted the game, parent withdrawal stays locked: winners settle in the child by carried proof, inherited losers require no transaction, and parent-lock cleanup is optional. A nonempty list additionally requires valid local indexes and one common depositor. | A nonempty list settles local deposits and routes any winning REP to their recorded depositor. An empty list returns after the outer lifecycle checks without settlement, state change, or event. | Per processed deposit, escalation-game `CarryDepositConsumed`; additionally `ClaimDeposit` for a winning payout. No event for an empty list |
| `withdrawForkedEscalationDeposits(outcome, proofs)` | Anyone; a nonempty list must name one beneficiary vault across all proofs | Game configured; operational child pool; valid final outcome. A nonempty list additionally requires an initialized continuation game, valid unconsumed winning proofs, and one common depositor. | A nonempty list verifies and consumes carried proofs, then pays winning child REP to the recorded depositor. An empty list returns after the outer lifecycle checks without proof verification, state change, or event. | Per processed proof, escalation-game `CarryDepositConsumed` and `ClaimDeposit`. No event for an empty list |
| `updateCollateralAmount()` | Anyone | No caller or lifecycle restriction. It returns unchanged when the accumulator is already at or beyond the clamped timestamp. | Accrues elapsed fees through question end while this pool's universe remains unforked; after that universe forks, its fork timestamp replaces question end as this pool epoch's cutoff, including a later question-end-to-fork interval. The cutoff is local to this pool: an activated child starts a separate fee epoch. It moves whole credited fees from collateral into the unallocated reserve and advances the accumulator. With positive elapsed time but zero fee-eligible allowance it clears denominator-specific remainder and advances the timestamp without charging fees. | `PoolAccountingCheckpoint` whenever positive elapsed time is processed, including the zero-allowance branch; no event for an unchanged timestamp |
| `updateRetentionRate()` | Anyone | No caller restriction. It returns unchanged when allowance is zero, the pool is not `Operational`, or the calculated rate equals the stored rate. | Recalculates the retention rate from current collateral and total bond allowance. | `PoolAccountingCheckpoint` only when the stored retention rate changes; no event for a no-op |
| `updateVaultFees(vault)` | Anyone for any address | No caller, nonzero-vault, or lifecycle restriction. | First updates pool accrual, then advances the vault fee index and fractional remainder, moves whole assigned fees from reserve to the vault, updates active-vault membership, and returns leftover reserve to collateral once a forked pool has checkpointed all eligible allowance. | Accrual `PoolAccountingCheckpoint` when due; `VaultAccountingCheckpoint` when the vault index, remainder, or fee debt changes; an additional `PoolAccountingCheckpoint` when pool accounting changes; no event when neither accrual nor vault or pool accounting changes |
| `performWithdrawRep(vault, repAmount)` | This pool's `OpenOraclePriceCoordinator` only | Fresh coordinator price; operational pool in an unforked universe; `isEscalationResolved()` is false; no vault REP escrow; sufficient vault and pool bond coverage after withdrawal. | Removes the requested proportional ownership, or the full ownership when the requested remainder would fall below the REP minimum, and transfers the resulting REP to `vault`. | REP `Transfer`, `PerformWithdrawRep`, and `VaultAccountingCheckpoint`, including a zero-value transfer/event path if the trusted coordinator supplies zero |
| `performLiquidation(...)` | This pool's `OpenOraclePriceCoordinator` only | Fresh coordinator price; operational pool in an unforked universe; `isEscalationResolved()` is false; target snapshot is unsafe; computed debt is positive and profitable; caller remains backed; both resulting vaults satisfy minimum floors. | Moves bounded debt and pool ownership from the unsafe target to the caller vault using the staged snapshot, updates both active-vault positions, and preserves the minimum REP/debt floors or performs the documented full-close sweep. | Fee-accrual checkpoints as needed, then `VaultLiquidated`, both vault `VaultAccountingCheckpoint` events, and `PoolAccountingCheckpoint` |
| `performSetSecurityBondsAllowance(callerVault, amount)` | This pool's `OpenOraclePriceCoordinator` only | Fresh coordinator price; operational pool in an unforked universe; `isEscalationResolved()` is false; vault and pool remain strictly allowance-backed; collateral stays within capacity; new allowance is zero or meets the minimum debt. | Accrues the vault, replaces its total and fee-eligible allowance contribution, clears allowance-denominator rounding carry, updates active membership, and recalculates retention. | Accrual checkpoints as needed; retention `PoolAccountingCheckpoint` if its rate changes; always final `VaultAccountingCheckpoint` and `PoolAccountingCheckpoint`, including when replacing an allowance with the same value |
| `setStartingParams(...)` | `SecurityPoolFactory` only | Factory caller. The pool has no internal one-shot or lifecycle guard; the factory exposes it only through atomic deployment wiring. | Sets the fee timestamp, retention, and collateral, seeds the coordinator with zero for an origin or the parent's last price for a child, then checkpoints initialization. | Coordinator `RepEthPriceSet` and `CoordinatorStateCheckpoint`, then pool `PoolAccountingCheckpoint`, even for zero or repeated values if the factory were to call again |
| `activateForkMode()` | `SecurityPoolForker` only | The pool has no inherited fixed outcome, so a fixed child cannot reopen for a later universe fork. There is no current-state guard otherwise. A configured game's drain must succeed or the entire activation reverts without propagating its reason data. | Sets `PoolForked`, accrues through the fork clamp, transfers the pool's entire REP balance to the forker, then makes the pool drain its configured escalation game's entire REP balance to the forker. Repeated calls are not lifecycle-guarded and transfer any balances replenished since the prior call before repeating the checkpoints. | Pool REP `Transfer` always, including at zero; configured-game REP `Transfer` only for a positive game balance; accrual checkpoint when due; always `PoolForkModeActivated` and fork-activation `PoolAccountingCheckpoint` |
| `initializeForkedEscalationGame(...)` | `SecurityPoolForker` only | No game is configured; downstream `startFromFork` parameters are valid. | Deploys and starts the pool's paused fork-continuation game with inherited timing and optional fixed outcome. | Escalation `GameContinuedFromFork`, then pool `EscalationGameSet` |
| `initializeForkCarrySnapshotWithResolutionBalances(...)` | `SecurityPoolForker` only | A game is configured; it is a fork continuation with no prior snapshot; leaf counts fit the MMR; supplied or computed snapshot ID matches the data. | Installs the continuation game's immutable carry peaks, counts, totals, resolution balances, and normalized nullifier roots. | `ForkCarryCheckpoint` |
| `resumeForkedEscalationGame()` | `SecurityPoolForker` only | A configured fork-continuation game that has not already resumed. | Sets the configured continuation game's resume timestamp and starts its remaining escalation clock. | `ForkContinuationResumed` |
| `setAwaitingForkContinuation(shouldAwait)` | `SecurityPoolForker` only | No lifecycle or value-change guard. | Stores whether complete-set minting must wait for continuation initialization. | `AwaitingForkContinuationSet`, including for a repeated value |
| `setSystemState(newState)` | `SecurityPoolForker` only | No transition or value-change guard. | Replaces the pool lifecycle state directly. | `SystemStateSet`, including for a repeated state |
| `configureVault(vault, poolOwnership, securityBondAllowance, vaultFeeIndex)` | `SecurityPoolForker` only | `vault` is nonzero; no lifecycle or value-change guard. | Tracks the vault, replaces its ownership, allowance, and fee index, clears pooled fee-index remainder when allowance changes, and updates active-vault ordering. | Always `VaultAccountingCheckpoint` and `PoolAccountingCheckpoint`, including when all supplied values repeat current state |
| `setOwnershipDenominator(newDenominator)` | `SecurityPoolForker` only | No lifecycle or value-change guard. | Replaces the pool ownership denominator. | `OwnershipDenominatorSet`, including for zero or a repeated value |
| `setTotalShares(newTotalShares)` | `SecurityPoolForker` only | No lifecycle or value-change guard. | Replaces stored `shareTokenSupply`, the denominator used by `sharesToCash` and complete-set redemption. | `ShareTokenSupplySet`, including for zero or a repeated value |
| `setPoolFinancials(newCollateral, newTotalBondAllowance, newFeeEligibleBondAllowance)` | `SecurityPoolForker` only | Total allowance covers collateral and fee-eligible allowance does not exceed total allowance; no lifecycle or value-change guard. | Replaces collateral and both allowance totals, resets the fee timestamp to the current block, and clears fee-index rounding carry. | `PoolAccountingCheckpoint`, including for repeated financial values |
| `authorizeChildPool(pool)` | `SecurityPoolForker` only | This parent pool is already authorized; candidate reports this share token; candidate universe has no different canonical pool. No pool-lifecycle guard. | Asks the lineage share token to establish `pool` as the canonical authorized pool for its universe; reauthorizing the same pool is a no-op. | `AuthorizationUpdated` only on first authorization; no event when already authorized |
| `transferEth(receiver, amount)` | `SecurityPoolForker` only | Fee liabilities are covered; `amount` fits both free pool balance and tracked collateral; `receiver` accepts the ETH call, including zero value. | Reduces tracked collateral by `amount`, checkpoints the reconciliation, and calls `receiver` with that ETH. At zero amount it reduces no collateral but still emits the checkpoint and performs a zero-value call; callback rejection rolls back the transaction and checkpoint. | `PoolAccountingCheckpoint`, including at zero amount; no dedicated ETH-transfer event |
| `addFeeEligibleSecurityBondAllowance(vault, amount)` | `SecurityPoolForker` only | The resulting fee-eligible allowance cannot exceed total security-bond allowance; no lifecycle, vault, positive-amount, or value-change guard. | Adds newly auction-claimed security-bond allowance to the live fee denominator and clears the pooled fee-index rounding remainder. | `VaultAccountingCheckpoint` and `PoolAccountingCheckpoint`, including at zero amount; the calling forker emits `ClaimAuctionProceeds` only after the broader credit workflow completes |
| Direct ETH transfer to `receive()` | Forker, this pool's truth auction, or parent pool only | Sender is one of the three authorized protocol addresses. Forced ETH bypasses this ordinary-call guard. | Accepts protocol-routed ETH used by migration and auction settlement. Forced ETH remains raw, unaccounted surplus rather than collateral or fees. | No dedicated receive event; the calling protocol step emits its own event |

## SecurityPoolForker

Freezes parent pools, creates selected child pools, migrates vault and escalation state, and settles collateral-repair auctions. [Source](../solidity/contracts/peripherals/SecurityPoolForker.sol)

Read surface: Use `zoltar`, `forkData`, `getMigratedRep`, `getForkActivationTime`, `isEscalationDepositClaimedDirectly`, `getEscalationDepositId`, `getDirectlyClaimedEscalationPrincipal`, `isEscalationWinnerHaircutPaidByFork`, `getEscalationMigrationEntitlementStatus`, `getOwnForkRepBuckets`, `getOwnForkMigrationStatus`, `getMigrationProxyAddress`, `getQuestionOutcome`, `repToPoolOwnership`, and `poolOwnershipToRep` to reconstruct fork progress and preview migration conversions.

### Child-game trust boundary

Fork entrypoints and child setup may receive contracts through unauthenticated pool lineages. A game relationship check is point-in-time: the reported nonzero game address must return the supplied pool or child from `securityPool()` when validated. This does not prove that an arbitrary game getter is immutable or that the address was factory-deployed. Child setup captures one reported game address, validates it before privileged use, and reuses that exact address for continuation backing and escrow work. When unresolved escalation requires a continuation and setup initially reports no game, initialization creates one; the forker then captures and validates it before continuation use. Combined vault migration passes the captured child/game pair into unresolved cleanup without reading the child getter again. Truth-auction completion performs a fresh point-in-time validation of the game reported then before checking continuation readiness. Genuine factory-deployed `EscalationGame` instances store their pool immutably, but safety on unauthenticated paths does not assume arbitrary contracts do.

<!-- Validated read ABI fingerprint: aa79d2d795e90ce0f0347186328bacbb1d5e28bbf7792359569ae44fead526f2 -->
<!-- Validated complete compiled ABI fingerprint: 8c7458fdb53493a7885c09e85c0b971cad80664f957b1912189abc9340a8c1a9 -->

| Transaction | Caller | Main prerequisites | State or asset effect | Primary signals |
| --- | --- | --- | --- | --- |
| `initiateSecurityPoolFork(securityPool)` | Anyone | Pool operational with no inherited fixed outcome; its universe already forked; fork state not initialized; if an escalation game exists, it reports the supplied pool from `securityPool()` when validated and the universe fork occurred before that game settled. This entrypoint does not authenticate the supplied address against a pool factory; see the [child-game trust boundary](#child-game-trust-boundary). | Freezes the supplied pool after an external universe fork, drains its pool and game REP, and records a migration snapshot keyed by that address. The snapshot is canonical only when the supplied pool is already registered by the configured `SecurityPoolFactory`. | `SecurityPoolForkSnapshot` and `ParentRepLocked`; additionally `EscalationRepDrainedAtFork` when unresolved escalation exists |
| `forkZoltarWithOwnEscalationGame(securityPool)` | Anyone | Pool operational with no inherited fixed outcome; its escalation game reports the supplied pool from `securityPool()` when validated and `canTriggerOwnFork()` is true because it recorded a local non-decision or inherited a threshold tie without a game-level fixed outcome; universe not already forked. The game-local predicate does not bypass the pool guard. This entrypoint does not authenticate the supplied address against a pool factory; see the [child-game trust boundary](#child-game-trust-boundary). | Uses the supplied pool game's non-decision to fork Zoltar, freezes that pool, and records own-fork REP buckets and snapshot state keyed by its address. The snapshot is canonical only when the supplied pool is already registered by the configured `SecurityPoolFactory`. | `SecurityPoolForkSnapshot`, `ParentRepLocked`, and Zoltar fork events; additionally `EscalationRepDrainedAtFork` when unresolved escalation exists |
| `migrateRepToZoltar(securityPool, outcomeIndices)` | Anyone | Migration proxy exists and the pool is `PoolForked`. Only a positive migration amount with at least one selected outcome checks the eight-week window, existing child `ForkMigration` state, outcome validity, and cumulative split bound. A zero amount skips those checks even when outcome values are supplied. | For a positive migration amount and nonempty list, ensures that the forker's recorded pool migration amount has been split into each selected child REP branch. A zero migration amount or empty list returns after the proxy and pool-state guards without per-outcome validation or events. | `MigrationRepSplit` and `ChildRepSplit` when a selected branch requires a new split; no event for a zero amount, empty list, or already-satisfied branch |
| `createChildUniverse(securityPool, outcomeIndex)` | Anyone | Parent in migration window; selected fork outcome is well formed; child pool is not already deployed; the selected child's reported nonzero escalation game passes the [child-game trust boundary](#child-game-trust-boundary). | Loads an already deployed child universe and REP token or deploys them when absent, then lazily deploys the selected child pool, coordinator, and auction; authorizes and links the child; captures and validates the child's escalation game; and initializes any continuation snapshot and materializes or sweeps child backing through that validated game. | `DeployChild` only when child REP was absent; always `SecurityPoolRegistered`, `DeploySecurityPool`, `AuthorizationUpdated`, `ChildPoolLinked`, and `OwnershipDenominatorSet`; `AwaitingForkContinuationSet`, `EscalationGameSet`, `GameContinuedFromFork`, `ForkCarryCheckpoint`, `MigrationRepSplit`, `ChildEscalationRepMaterialized`, and `ChildPoolRepSwept` as continuation and backing state requires |
| `migrateVault(securityPool, outcomeIndex)` | Vault owner for its unlocked position | Migration window open; the selected child's reported nonzero escalation game passes the [child-game trust boundary](#child-game-trust-boundary). The optional unresolved-lock cleanup wrapper calls this function first to migrate any unlocked state. | Moves the caller's currently unlocked REP ownership, allowance, fees, and collateral into one child pool. Repeat calls can have no additional unlocked state to move. | `VaultMigrationCheckpoint` |
| `migrateVaultWithUnresolvedEscalation(securityPool, vault, childOutcomeIndex)` | The named vault | Migration window open; caller equals `vault`; selected child not already recorded for this optional cleanup; the selected child's reported nonzero escalation game passes the [child-game trust boundary](#child-game-trust-boundary). | First runs ordinary migration for the same vault, which may move its unlocked ownership, allowance, fees, and collateral to the selected child. It returns the selected child and its captured, validated escalation game to the unresolved-cleanup phase, which reuses those exact addresses without reading the child's game again. The cleanup then clears that vault's parent unresolved-lock accounting in constant-size work and records it; the cleanup neither funds escalation backing nor authorizes carried proofs. | Vault migration events plus `EscalationMigrationEntitlementInitialized` on first export and `EscalationMigrationEntitlementMaterialized` for the selected child |
| `claimForkedEscalationDeposits(...)` | The named vault | Caller equals `vault`; unresolved escalation existed when the pool initiated its own fork and the parent game still satisfies `canTriggerOwnFork()` by having either a local non-decision or an inherited threshold tie without a fixed outcome; selected child can be created or loaded, remains in `ForkMigration`, has a continuation game that passes the [child-game trust boundary](#child-game-trust-boundary), and is inside the eight-week claim window. A nonempty list additionally requires the matching winning outcome, deposits belonging to `vault`, and unclaimed deposit identities. | First gets or lazily deploys the selected child universe, REP token, pool, coordinator, and auction, then captures and validates the child's escalation game and uses that same game for continuation backing and escrow payment. A nonempty list claims winning own-fork parent deposits and records their stable identities against descendant replay. An empty list still performs child setup and emits a zero-valued claim summary. | `DeployChild`, `SecurityPoolRegistered`, `DeploySecurityPool`, `AuthorizationUpdated`, `ChildPoolLinked`, `OwnershipDenominatorSet`, `AwaitingForkContinuationSet`, `EscalationGameSet`, `GameContinuedFromFork`, `ForkCarryCheckpoint`, `MigrationRepSplit`, `ChildEscalationRepMaterialized`, and `ChildPoolRepSwept` as setup requires; per claimed deposit, `CarryDepositConsumed` and `ClaimDeposit`; escrow record/export events when REP is paid; always `ClaimForkedEscalationDepositsToWallet`, including for an empty list |
| `startTruthAuction(securityPool)` | Anyone | Child migration window ended; pool is in fork migration; required child REP is available. If unresolved escalation existed at fork, any game reported during immediate completion passes the [child-game trust boundary](#child-game-trust-boundary). | Copies the frozen parent's remaining economic claim supply into the child, closes migration accounting, and either reopens a fully backed child or starts its repair auction. | `ShareTokenSupplySet` and `TruthAuctionStarted`; immediate no-auction paths also emit `TruthAuctionFinalized` and pool accounting checkpoints |
| `finalizeTruthAuction(securityPool)` | Anyone | Truth auction started, its one-week window has passed, and `msg.value` is zero. If unresolved escalation existed at fork, the game reported at completion passes the [child-game trust boundary](#child-game-trust-boundary). | Finalizes the ended auction, accounts migration-routed collateral plus accepted bid ETH, activates the child at that collateral level, and fixes bidder ownership and allowance rates. A nonzero repair contribution is rejected. | `TruthAuctionFinalized`, auction `AuctionFinalized`, and pool accounting checkpoints |
| `settleAuctionBids(securityPool, vault, claimTickIndices, refundTickIndices)` | Anyone on behalf of the named bidder vault | At least one index; before finalization the claim list must be empty and refund indexes must be eligible; after finalization all indexes must belong to the named vault and remain unsettled. | Before finalization, refunds only provably losing bids. After finalization, combines claim and refund indexes into one settlement withdrawal and credits each fixed-position REP and allowance result; a winning dust bid may receive allowance even when its REP share rounds to zero. | Underlying auction `BidSettled`; `ClaimAuctionProceeds` when REP or allowance is credited |
| `claimAuctionProceeds(securityPool, vault, tickIndices)` | Anyone on behalf of the named bidder vault | Auction finalized. A nonempty list additionally requires every index to belong to the named vault and remain unsettled. | For a nonempty list, withdraws finalized bid settlements, converts purchased REP into child-pool ownership, and independently credits the bid positional allowance share. A winning dust bid can receive positive allowance when its REP share rounds to zero. For an empty list, the underlying auction withdrawal returns three zeros and the wrapper exits after the finalization guard without validating bids or the named beneficiary, calling it, changing state, or emitting events. | For processed bids, underlying auction `BidSettled`; `ClaimAuctionProceeds` when REP or allowance is credited; no event for an empty list |
| `initializeChildForkedEscalationGameIfNeeded(parent, child, childEscalationGame)` | This `SecurityPoolForker` contract only, through its migration delegate callback | External caller is the forker itself; parent and child match the active migration path; a supplied nonzero game passes the [child-game trust boundary](#child-game-trust-boundary). | Allows delegated migration code to initialize a child continuation while preserving the forker as the authoritative caller and the already captured child-game identity. When unresolved escalation requires a continuation and no game existed, it captures and validates the game created by initialization before any continuation use. | `ChildEscalationRepMaterialized` and escalation-continuation events when initialization is required |
| Direct ETH transfer to `receive()` | The canonical child-pool truth auction registered by this forker during `ChildPoolLinked` | `trustedAuctionAddresses[msg.sender]` was set when the forker linked that canonical child pool and emitted `ChildPoolLinked`. | Accepts auction ETH during forker-controlled auction finalization. | No dedicated receive event; auction `AuctionFinalized` is followed by forker `TruthAuctionFinalized` and pool accounting checkpoints |

## EscalationGame

Escrows outcome REP, raises the running resolution cost, detects non-decision, and settles local or carried deposits. [Source](../solidity/contracts/peripherals/EscalationGame.sol)

Read surface: Base getters are `securityPool`, `repToken`, `activationTime`, `nonDecisionThreshold`, `startBond`, `nonDecisionTimestamp`, `nonDecisionState`, `forkContinuation`, `forkElapsedAtStart`, `forkResumedAt`, `fixedQuestionOutcome`, `nodes`, `escrowedRepByVault`, and `totalEscrowedRep`. Use `previewDepositOnOutcome`, `computeIterativeAttritionCost`, `computeTimeSinceStartFromAttritionCost`, `totalCost`, `getEscalationGameEndDate`, `getQuestionResolution`, `getFinalQuestionResolution`, `hasReachedNonDecision`, `canTriggerOwnFork`, `getBindingCapital`, `getOutcomeBalances`, `getDepositsByOutcome`, `getDepositsByOutcomeLength`, `forkCarrySnapshotInitialized`, `getOutcomeState`, `getForkCarrySnapshot`, `getForkCarryRoots`, `isForkCarryFundingComplete`, `getCarryLeafPageByOutcome`, `getProofConsumedCarriedDepositIndexesByOutcome`, `getLocalUnresolvedPrincipalByVaultAndOutcome`, and `getForkedEscrowByVaultAndOutcome` for calculations, lifecycle authorization, pages, carry state, and escrow. Ordinary users route deposits and withdrawals through `SecurityPool`.

<!-- Validated read ABI fingerprint: ed805db82536ad060437fa3f82ceb85839349441a6fede83e2fd40ee761e13d5 -->
<!-- Validated complete compiled ABI fingerprint: 944f05572e55db85409418510e1ef477a80943359d153df5641fb15ce0508d68 -->

| Transaction | Caller | Main prerequisites | State or asset effect | Primary signals |
| --- | --- | --- | --- | --- |
| `start(startBond, nonDecisionThreshold)` | `EscalationGameFactory` contract during atomic deployment | Game not already started; threshold exceeds the positive start bond; both are at least 1 REP. | Initializes a local game and sets activation three days after deployment. | `GameStarted` |
| `startFromFork(startBond, nonDecisionThreshold, elapsedAtFork, fixedQuestionOutcome, winnerHaircutPaidByFork, forkCarryInitialBacking)` | Immutable owner (`EscalationGameFactory`) during atomic continuation deployment | Game not started; threshold exceeds the positive start bond; both are at least 1 REP; inherited elapsed time is no greater than seven weeks. | Initializes a paused continuation with inherited elapsed time, an optional fixed matching child outcome, and immutable fork-time haircut/backing accounting. It does not start the remaining clock until `resumeFromFork`. | `GameContinuedFromFork` |
| `resumeFromFork()` | Owning `SecurityPool` in the supported workflow; the immutable owner is also admitted, but its factory contract exposes no relay | Fork-continuation mode and not previously resumed. | Records the resume timestamp and starts the remaining continuation clock. After the deadline, `getFinalQuestionResolution` returns the fixed outcome when one is present. | `ForkContinuationResumed` |
| `recordDepositFromSecurityPool(...)` | Owning `SecurityPool` only | Explicit non-decision state is `None`; game unresolved; valid outcome; preview and accepted cumulative amount match; room remains below threshold. | Appends an accepted local deposit, updates outcome and vault escrow, and records its carry leaf. | `LocalDepositAppended`, `DepositOnOutcome`, optionally `NonDecisionReached` |
| `withdrawDeposit(uint256 depositIndex, outcome)` | Owning `SecurityPool` only | Explicit non-decision state is `None`; non-`None` supplied outcome; game final; game and pool final outcomes match; valid unsettled local deposit index. | Consumes one local deposit after resolution. A winner is paid after its haircut; a loser only retires its escrow accounting. | `CarryDepositConsumed` and `VaultEscrowUpdated`; for a winner, `ClaimDeposit`, positive REP payout `Transfer`, and haircut burn signals when nonzero |
| `initializeForkCarrySnapshotWithResolutionBalances(...)` | Owning `SecurityPool` only | Fork-continuation mode; no prior snapshot; each leaf count fits the MMR; supplied nonzero snapshot ID equals the hash of the normalized data. | Installs the immutable inherited peaks, leaf counts, carry totals, resolution balances, and normalized nullifier roots; zero snapshot ID selects the computed ID. Two or more threshold-full inherited balances set `nonDecisionState` to `InheritedThresholdTie` without creating a local timestamp. | `ForkCarryCheckpoint`; additionally `InheritedThresholdTie` when the installed balances meet the non-decision threshold |
| `claimDepositForWinning(depositIndex, outcome)` | Owning `SecurityPool` or its `SecurityPoolForker` | Non-`None` supplied outcome and valid unsettled local deposit with sufficient escrow. This entrypoint itself does not check final resolution or that the supplied outcome won; its trusted caller selects that path. | Consumes a selected local deposit as a winner, consumes its vault escrow, burns the computed haircut when nonzero, and transfers the remaining positive REP payout to its recorded depositor. | `CarryDepositConsumed`, `VaultEscrowUpdated`, `ClaimDeposit` with `transferredRep = true`; REP payout `Transfer` and haircut burn signals only when their amounts are positive |
| `claimDepositForWinningWithoutTransfer(depositIndex, outcome)` | Owning `SecurityPool` or its `SecurityPoolForker` | Valid in-range supplied outcome and unsettled local deposit with sufficient escrow. Unlike the transferring form, it has no explicit non-`None` guard; neither form checks final resolution or that the outcome won. | Consumes a selected local deposit and its vault escrow and returns the computed winner amount to the trusted caller, but deliberately neither transfers REP nor burns the computed haircut. | `CarryDepositConsumed`, `VaultEscrowUpdated`, and `ClaimDeposit` with `transferredRep = false`; no REP transfer or haircut burn |
| `exportUnresolvedDeposit(depositIndex, outcome)` | Owning `SecurityPool` or its `SecurityPoolForker` | Non-`None` outcome and a valid unsettled local deposit. Final resolution is not 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(CarriedDepositProof proof, outcome)` | 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 haircut unless the fork already paid it. | `CarryDepositConsumed` and `ClaimDeposit` with `transferredRep = true`; REP payout `Transfer` and haircut burn signals only when positive |
| `exportVaultUnresolvedTotals(vault, repReceiver)` | Owning `SecurityPool` or its `SecurityPoolForker` | `vault` is nonzero and has not exported before. There is no explicit nonzero-receiver guard: a zero receiver succeeds when the total is zero but the token rejects it when a positive transfer is attempted. | Marks the vault's local unresolved totals exported exactly once, clears each outcome amount, consumes aggregate unresolved and escrow accounting when positive, and transfers the positive total to `repReceiver`. | Always `VaultUnresolvedTotalsExported`, including when every amount is zero; `VaultEscrowUpdated` and REP `Transfer` only for a positive total |
| `exportVaultUnresolvedTotalsWithoutTransfer(vault)` | Owning `SecurityPool` or its `SecurityPoolForker` | `vault` is nonzero and has not exported before. | 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 | `receiver` is nonzero; no positive-balance requirement. The protocol reaches this call from the owning pool after `activateForkMode` enters `PoolForked`. | Transfers the game's full REP balance to `receiver`. A zero balance returns zero without a transfer or event. | REP `Transfer` for a positive balance; no event at zero balance |
| `recordForkedEscrowForOutcome(depositor, outcome, sourcePrincipal, childRepAmount)` | Owning `SecurityPool` or its `SecurityPoolForker` | Outcome is not `None`; depositor is nonzero. A nonzero call additionally requires positive source principal. | Accumulates source principal and child REP escrow for the vault and outcome. 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; 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; no REP transfer; no event for an already-empty export |
| `sweepResidualRepToSecurityPool()` | Anyone | Final outcome; no unresolved principal; no vault escrow; positive residual balance. | Returns otherwise stranded residual REP to the owning pool. | `ResidualRepSweptToSecurityPool` |

## OpenOraclePriceCoordinator

Obtains a fresh REP-per-ETH price and gates withdrawal, allowance, and liquidation operations behind it. [Source](../solidity/contracts/peripherals/OpenOraclePriceCoordinator.sol)

Read surface: Configuration getters are `MAX_PENDING_SETTLEMENT_OPERATIONS`, `OPEN_INTEREST_DIVIDER`, `reputationToken`, `securityPool`, `openOracle`, `weth`, `gasConsumedOpenOracleReportPrice`, `gasConsumedSettlement`, `gasUnitsForOneDispute`, `targetPriceErrorForDispute`, `openOracleSecurityMultiplierBps`, `settlementTime`, `disputeDelay`, `protocolFee`, `feePercentage`, `multiplier`, `timeType`, `trackDisputes`, `protocolFeeRecipient`, `escalationHaltMultiplierBps`, `maxSettlementBaseFeeMultiplierBps`, and `minLiquidationPriceDistanceBps`. Current report and operation getters are `pendingReportId`, `pendingReportSponsor`, `pendingOperationSlotId`, `lastSettlementTimestamp`, `lastPrice`, `pendingReportMaxSettlementBaseFee`, `stagedOperationCounter`, and `stagedOperations`. Use `isPriceValid`, `minimumToken1Report`, `getRequestPriceEthCost`, `getQueuedOperationEthCost`, `getSettlementCallbackGasLimit`, `getPendingOperationSlot`, `getActiveStagedOperationCount`, `getActiveStagedOperations`, `getPendingSettlementOperationCount`, and `getPendingSettlementOperationIds` for derived or paged state.

<!-- Validated read ABI fingerprint: f86d47172374a06e4f6a9eb2e47f8cca1d7c314b30183bd1c4e3d0495e5d6ce4 -->
<!-- Validated complete compiled ABI fingerprint: 77123164dedd551357fc458328598db7d57ffedf791db0943c040894b395cd83 -->

| Transaction | Caller | Main prerequisites | State or asset effect | Primary signals |
| --- | --- | --- | --- | --- |
| `requestPriceIfNeededAndStageOperation(...)` with funding when stale | Vault owner for self withdrawal/allowance; a different vault for liquidation. While a report is pending, only that report sponsor may stage more operations. | `securityPool.isEscalationResolved()` is false; valid target and nonzero amount except zero allowance; timeout from 1 second through 5 minutes. Bounty, buffered funding for at least the dynamic WETH minimum and coordinator-derived REP side, and approvals are required only when this call opens a new report; the caller may request a larger initial WETH amount. Staging beside a pending report or queued rejected-report work does not open or fund another report. The caller must accept any positive unused-ETH refund. | Records the operation, executes immediately with a fresh price, or attaches it to a bounded pending settlement batch and opens a report when required. If unused ETH is positive, the final caller refund uses a low-level callback; rejection rolls back the entire transaction, including any queueing, immediate execution, or newly opened report. | `StagedOperationQueued`, possibly `PriceRequested`, then `ExecutedStagedOperation`; authoritative `CoordinatorStateCheckpoint` records |
| `requestPrice(proposedRepPerEthPrice, requestedInitialWeth)` with report funding | Anyone when no fresh price or report is pending | Cached price stale; no pending report; nonzero proposed REP/ETH price, ETH bounty, and funding and approvals for at least the dynamic WETH minimum plus matching REP. Zero requested WETH uses the minimum; a larger request voluntarily increases the initial report. The caller must accept any positive excess-ETH refund. | Opens and atomically funds a fresh WETH/REP report without staging a new operation, then refunds any positive excess ETH through a low-level caller callback. Callback rejection rolls back the report and initial position. | `PriceRequested` and `CoordinatorStateCheckpoint` |
| `executeStagedOperation(operationId)` | Anyone | Operation exists and coordinator price is fresh; lifecycle failures are emitted rather than retried. | Consumes and attempts one active staged operation using the current fresh price. Price-report funding is independent of the operation's notional; the downstream operation applies its own protocol bounds. | `ExecutedStagedOperation` and `CoordinatorStateCheckpoint` |
| `recoverSettledPendingReport()` | Anyone | A pending report ID exists and its stored OpenOracle `finalizedGame(reportId).settlementTimestamp` is nonzero. | Clears a pending report whose normal callback path did not clear coordinator state and consumes its pending-operation slot. | `PendingReportRecovered`, optionally `PendingOperationRecoveryConsumed`, and `CoordinatorStateCheckpoint` |
| `openOracleCallback(...)` | Configured `OpenOracle` only | Callback report matches the pending report; high basefee or zero values reject the price after clearing pending report state. | A valid settlement updates the price and auto-executes the bounded pending batch. A rejected settlement clears pending-report state but leaves staged operations queued for a later valid price path. | `PriceReported` or `PriceReportRejected`; operation execution events; authoritative `CoordinatorStateCheckpoint` records |
| `setSecurityPool(pool)` | Anyone while `securityPool` remains zero; normal factory deployment calls atomically | Current `securityPool` is zero; the argument itself is not required to be nonzero. | A nonzero value binds the pool permanently. A zero value emits and checkpoints zero but leaves the setter callable. Normal factory deployment supplies the nonzero canonical pool before returning the coordinator. | `SecurityPoolSet` and `CoordinatorStateCheckpoint` |
| `setRepEthPrice(price)` | Configured nonzero `SecurityPool` only | Caller equals the configured pool. | Seeds the coordinator's price value, including zero, for inherited child state. | `RepEthPriceSet` and `CoordinatorStateCheckpoint` |

## ShareToken

Stores universe-aware ERC-1155 outcome shares and materializes a holder's persistent source entitlement in selected fork branches. [Source](../solidity/contracts/peripherals/tokens/ShareToken.sol)

Read surface: Base and relationship getters are `name`, `symbol`, `zoltar`, `canonicalPoolByUniverse`, `_balances`, `_supplies`, and `_operatorApprovals`. Standard ERC-1155 reads are `supportsInterface`, `balanceOf`, `totalSupply`, `balanceOfBatch`, and `isApprovedForAll`; protocol-specific reads are `isAuthorized`, `getChildUniverseId`, `totalSupplyForOutcome`, `maximumOutcomeSupply`, `balanceOfOutcome`, `balanceOfShares`, `getMigratedShareAmount`, `getTokenId`, `getTokenIds`, and `unpackTokenId`.

<!-- Validated read ABI fingerprint: 3b68e6bd8e3cea9398317397c9ab93da54e67d7aa234933be4b4cdcd95e884d9 -->
<!-- Validated complete compiled ABI fingerprint: 57037ae78e2547bcb28e5a683091fe0a03301902f835b0b2600bcbd112fd5dda -->

| Transaction | Caller | Main prerequisites | State or asset effect | Primary signals |
| --- | --- | --- | --- | --- |
| `setApprovalForAll(operator, approved)` | Any token account setting its own operator approval | The operator differs from the caller. | Sets or clears the operator's authority over all of the caller's outcome-token balances. | `ApprovalForAll` |
| Both `safeTransferFrom(...)` overloads | Share holder or approved ERC-1155 operator | Caller owns the source balance or has operator approval; the source account has not materialized that token into any child branch; destination is nonzero; the source balance is sufficient; a contract recipient accepts the ERC-1155 callback. | Transfers one outcome-token balance without changing supply. | `TransferSingle` |
| Both `safeBatchTransferFrom(...)` overloads | Share holder or approved ERC-1155 operator for a nonempty batch; any caller for an empty batch | ID and value array lengths match. A nonempty batch also requires holder or operator authority, no listed source token that the source account has already materialized into a child branch, a nonzero destination, sufficient source balances, and an accepting ERC-1155 callback from a contract recipient; the empty-batch no-op performs none of those checks. | A nonempty batch transfers each listed outcome-token balance without changing supply. Equal empty ID and value arrays return as a no-op without an event. | `TransferBatch` for a nonempty batch; no event for an empty batch |
| `migrate(fromId, targetOutcomeIndexes)` | Holder of the source token ID | Source universe forked; canonical source pool is `Operational` or `PoolForked`, and an `Operational` source has no inherited fixed outcome because auto-fork activation rejects one; positive source balance; nonempty, strictly increasing, well-formed outcomes; every target in a multi-target call already has a canonical child pool; after the branch-creation window, a single target must also already exist; at least one selected child has an unmaterialized balance; a contract holder accepts `onERC1155Received` for every target mint. | If needed, first freezes the operational source pool and records its fork snapshot. A single-target call may lazily create that child while the branch-creation window is open. It keeps and locks the holder's source entitlement, then mints each selected child-universe token ID up to the current source balance. Later source additions materialize only the unminted delta. A contract holder receives the ERC-1155 single-receiver callback for each mint; rejection rolls back the mint and preceding fork or child setup. | `PoolForkModeActivated`, `PoolAccountingCheckpoint`, `SecurityPoolForkSnapshot`, `ParentRepLocked`, and optionally `EscalationRepDrainedAtFork` when auto-forking; `SecurityPoolRegistered`, `DeploySecurityPool`, `AuthorizationUpdated`, and `ChildPoolLinked` when lazily deploying, plus `DeployChild`, `ChildRepSplit`, `ChildPoolRepSwept`, `EscalationGameSet`, `GameContinuedFromFork`, `ForkCarryCheckpoint`, and `ChildEscalationRepMaterialized` as applicable; then one ERC-1155 mint `TransferSingle` and `Migrate` per materialized target on successful callbacks |
| `authorize(securityPoolCandidate)` | Initially authorized `SecurityPoolFactory` for an origin pool; an authorized parent `SecurityPool` for a child pool | Caller is already authorized; the candidate reports this exact share token; its universe has no different canonical pool. | Establishes the candidate as `canonicalPoolByUniverse` for its universe and adds it to the set allowed to mint, burn, and authorize descendants. Reauthorizing the same candidate is a no-op. | `AuthorizationUpdated` on first authorization; no event when the same candidate is already authorized |
| `mintCompleteSets(universeId, account, amount)` | An authorized `SecurityPool` | Caller is authorized; `account` is nonzero; `amount` is positive; a contract account accepts `onERC1155BatchReceived`. | Mints `amount` each of Invalid, Yes, and No to `account`, then invokes its ERC-1155 batch-receiver callback when it is a contract. Rejection rolls back the mint and the authorized pool's surrounding transaction. | `TransferBatch` on a successful callback |
| `burnCompleteSets(universeId, account, amount)` | An authorized `SecurityPool` | Caller is authorized; `account` is nonzero and owns at least `amount` of every outcome. | Burns `amount` each of Invalid, Yes, and No from `account`; global outcome supplies may differ. | `TransferBatch` |
| `burnTokenIdAndGetRemainingSupply(tokenId, account)` | An authorized `SecurityPool` | `account` is nonzero; caller is authorized. | Burns `account`'s full balance of `tokenId` and returns the burned amount and that token ID's remaining supply. | `TransferSingle`, including when the burned balance is zero |

## UniformPriceDualCapBatchAuction

Collects ETH bids under ETH-raise and REP-sale caps, computes one clearing result, and supports paged settlement. [Source](../solidity/contracts/peripherals/UniformPriceDualCapBatchAuction.sol)

Read surface: Auction summary getters are `maxRepBeingSold`, `ethRaiseCap`, `finalized`, `clearingTick`, `ethFilledAtClearing`, `ethRaised`, `totalRepPurchased`, `auctionStarted`, `minBidSize`, `owner`, `underfunded`, `underfundedThreshold`, `underfundedWinningEth`, and `activeTickCount`. Use `computeClearing`, `previewFinalization`, `tickToPrice`, `getTickSummary`, `getTickCount`, `getTickPage`, `getActiveTickPage`, `getBidCountAtTick`, `getBidPageAtTick`, `getBidderBidCount`, and `getBidderBidPage` before finalizing or submitting settlement indexes.

<!-- Validated read ABI fingerprint: 186753be736e928a7f869de0ce48c0e0d02d4000940ab96c8f656d7bdbae28ca -->
<!-- Validated complete compiled ABI fingerprint: 665c49ae04480dac83863ace573f093aa6bc0815ee64a65c8deb37f388bfa2da -->

| Transaction | Caller | Main prerequisites | State or asset effect | Primary signals |
| --- | --- | --- | --- | --- |
| `startAuction(ethRaiseCap, maxRepBeingSold)` | Auction owner (`SecurityPoolForker`) only | Auction not previously started; both caps are positive. | Starts the one-week auction and fixes its two caps and minimum bid. | `AuctionStarted` |
| `submitBid(tick)` with ETH | Any bidder | Auction active and unfinalized; before one-week deadline; bid meets `minBidSize`; tick maps to nonzero price. | Adds ETH demand at the selected positive-price tick while extending that tick's append-only cumulative bid and refund history, including when a fully refunded tick becomes active again. | `BidSubmitted` |
| `refundLosingBids(tickIndices)` | Bidder for its own bids | Auction started and unfinalized; auction has reached a clearing price; bidder accepts the refund ETH call, including zero value. Nonempty indexes additionally belong to the caller and are strictly losing and unrefunded. | A nonempty list marks and refunds the caller's bids already provably below the current clearing tick. An empty list changes no bids but still calls the bidder with zero ETH. | `BidSettled` per refunded bid; no event for an empty list |
| `refundLosingBidsFor(bidder, tickIndices)` | Auction owner (`SecurityPoolForker`) only; public callers use `settleAuctionBids` | Named bidder is nonzero; auction started and unfinalized; auction has reached a clearing price; bidder accepts the refund ETH call, including zero value. Nonempty indexes additionally belong to that bidder and are strictly losing and unrefunded. | A nonempty list marks and refunds a named bidder's bids already provably below the current clearing tick. An empty list changes no bids but still calls the bidder with zero ETH. | `BidSettled` per refunded bid; no event for an empty list |
| `finalize()` | Auction owner (`SecurityPoolForker`) only; users reach it through `finalizeTruthAuction` | Auction started, not finalized, and one-week deadline reached; owner accepts the proceeds ETH call, including zero value. | Fixes the clearing mode, clearing tick, ETH totals, and aggregate REP allocation, then calls the owner with the resulting proceeds, including when zero. A rejected call reverts finalization and its event. | `AuctionFinalized` |
| `withdrawBids(withdrawFor, tickIndices, proRataTotal)` | Auction owner only | Auction finalized; caller is owner. Nonempty indexes belong to `withdrawFor` and remain unsettled; if their aggregate refund is positive, `withdrawFor` accepts that ETH call. | For a nonempty list, returns refunds, purchased REP, and a companion pro-rata allocation for the selected beneficiary bids so the forker can credit pool ownership and allowance. Withdrawal-time allocation assigns division dust from deterministic cumulative ETH positions, making each payout independent of claim order. An empty list returns three zeros without changing bids, emitting events, or calling the beneficiary. | `BidSettled` per processed bid; no event for an empty list |
