OpenOracle integration reference

OpenOracle supplies a fresh REP/ETH price for Statoblast's solvency-sensitive operations. It does not decide market truth; local Escalation Games and Zoltar remain responsible for truth and branching.

The OpenOracle explanation covers why Statoblast uses a contestable price and which operations depend on it. This page specifies the integration: formulas, parameters, and settlement-callback behavior. Per-function callers, preconditions, and events are in the coordinator contract reference.

Token pair and cached price

Statoblast configures WETH as token1 and REP as token2. Keeping WETH on the exact side lets the coordinator size the report directly from ETH-denominated gas costs without first assuming a REP/ETH conversion price. When a report settles, the coordinator converts the settled token amounts into REP per ETH:

lastPrice = amount2 ⋅ 1018 amount1

The settled REP amount (amount2) is scaled by the fixed price precision and divided by the settled WETH amount (amount1).

This raw-amount ratio is valid because the configured WETH and REP contracts both use 18 decimals. The coordinator does not normalize token decimals in the settlement callback.

An accepted report becomes the coordinator's cached REP/ETH price. lastSettlementTimestamp records settlement eligibility: the final report timestamp plus settlementTime. The freshness window starts there, so settling late cannot extend it. The shared feed freshness window is settlementTime plus one hour on Sepolia or five minutes on other chains. With the mainnet eight-minute challenge period, a shared price is usable for 780 seconds after eligibility, or at most 21 minutes after the final report. priceValidUntil() returns the canonical expiry; a price is stale at that timestamp. The coordinator does not meter operation volume during the window.

Shared feeds size reports and escalation halts against the largest of current portfolio commitment, backing demand and the maximum commitment a preparing branch auction can add to chosen backing. The feed reads these aggregates without scanning questions or bidders. Unused capacity from an oversized earlier report does not increase the minimum size of the next report.

A shared feed permits concurrent candidates, including renewal before the accepted price expires. Each candidate has its own SharedPoolReportEscrow, which holds its reporter identity and funding credits. pendingReportId and the associated pending getters identify only the latest candidate; they do not enumerate or exclude other pending candidates. A pending, disputed or rejected report never extends accepted-price freshness.

Shared acceptance atomically checkpoints portfolio fees under the previous price and updates capital eligibility. A failed mandatory checkpoint rolls back acceptance. Ordinary capital operations execute separately and recheck current safety constraints against the accepted price. An optional batch of sponsor-authorized capital operations is attempted immediately after acceptance.

Portfolio branch preparation

SecurityPoolFactory.preparePortfolioPriceFeed(sourcePool, child) prepares the canonical child feed without deploying a child question. sourcePool must be a canonical question pool already admitted to this portfolio, with its portfolio binding recorded by the factory. The configuration seed is itself a canonical portfolio question. SecurityPoolPortfolio.isPriceReportingOpen(child) permits requests and acceptance after startBranch, until the fixed native recapitalization deadline at week nine. From that deadline until activation, the accepted observation is frozen. Reporting reopens on activation if the child universe has not forked; a forked universe rejects new prices. Late branch preparation does not extend the window.

An accepted preparation report caches the price and funded exposure; it does not activate trading, start holding fees or start imported positions’ liquidation history. Activation uses the cached price only while it remains fresh. A stale or absent price does not block branch activation. Callbacks during a closed window reject the candidate price while preserving report funding recovery.

Shared report coverage and capital prices

During auction preparation, minimumToken2ReportAttoRep() requires one hundredth of fresh sale inventory, rounded up. minimumToken1ReportAttoEthForPrice(price) also raises the WETH minimum enough to fund that REP amount at the proposed price. Direct sponsorship through requestPortfolioPrice rejects a signed WETH budget below the required amount. Acceptance checks both sides: acceptedRepExposureLimitAttoRep is final REP funding times 100. An arbitrarily cheap proposed REP price therefore cannot remove the REP inventory challenge requirement.

A canonical acceptance sets acceptedExposureLimitAttoEth to (final WETH − priority-fee report component) × 100 and increments acceptedEpoch. An ordinary setCommitment raise cannot lift aggregate exposure above that accepted limit. Pending funding grants no capacity. To raise a commitment, an owner can instead call setCommitmentWithReport(reportId, commitment) with an independently settled, fresh candidate whose final funding covers the projected total exposure. reportAuthorization(reportId, newExposure) validates that proof even if a newer, smaller canonical report superseded it.

For accepted price q, target error e, and percentage precision P = 10,000,000, the upper bound is q × P / (P − e), rounded up, and the liquidation bound is q × P / (P + e), rounded down. Capital entry, withdrawals, capacity and fee eligibility use the conservative upper bound; rewarded adverse actions use the lower bound. Proof authorization also retains the higher of the owner’s current conservative price and the proof’s upper bound for that owner’s collateral checks until a later canonical epoch covers the enlarged live exposure. Selecting a smaller report cannot remove this owner-specific floor.

Report flags

The coordinator always submits flags 7: FLAG_TIME_TYPE (1, a timestamp clock), FLAG_TRACK_DISPUTES (2, per-dispute history), and FLAG_STORE_ALL (4, the complete report state in storage). It never sets the optional flags 8, 16, 32, or 64; the OpenOracle provenance record identifies the vendored source and build profile.

Integration architecture

Each question has an OpenOraclePriceCoordinator adapter attached to one SharedPoolPriceFeed per portfolio and universe. The feed owns the accepted REP/ETH price and freshness clock. Every candidate has its own escrow. The factory authenticates coordinator creation and binds each question once.

A child universe gets a new feed for its own REP token, initially with no accepted price. Adding a question does not reset an existing feed. Capital deposits, commitments and retirement use the portfolio directly. Capital operations may also execute through an ordered sponsor-authorized batch attached to a shared report.

Price request lifecycle

  1. The sponsor approves WETH and universe REP, chooses a candidate price and report budget, and opens a report through a question coordinator or the shared feed.
  2. OpenOracle accepts valid corrections during the challenge window. A correction replaces the current reporter and restarts settlement timing.
  3. After the challenge window, anyone can settle the report. Its isolated escrow validates the result and offers it to the shared feed.
  4. The feed accepts only a qualifying, fresh observation with sufficient economic coverage. Rejected candidates cannot invalidate the previously accepted observation.
  5. Owners and keepers normally submit capital operations separately. A report may instead carry a sponsor-authorized operation batch; both paths recheck current safety constraints.

Escalation reports use wallet REP in separate reporter custody. They do not consume underwriting REP or use an oracle operation queue.

Funding and report ownership

The sponsor funds its own WETH, REP and transaction gas. The minimum public settlement bounty is 101 attoETH; it does not reimburse the sponsor’s gas. The sponsor may supply a larger bounty.

requestPriceCostAttoEth=101

REQUEST_BOUNTY_OFFSET_ATTO_ETH is 101 attoETH. The ordinary-report callback budget is 4,000,000 gas; callers pay their own transaction gas.

requestPortfolioPrice(proposedRepPerEthPrice, requestedInitialAttoWeth, bountyAttoEth) transfers exactly the reviewed WETH budget and its corresponding REP from the caller. It rejects a budget below the inclusion-time minimum instead of silently increasing it. Only the recorded sponsor receives that candidate’s returned funding. Portfolio settlement collateral does not fund reports.

A coordinator request forwards the specified bounty and refunds excess native ETH to the caller. Rejecting that refund reverts the whole request. A direct feed request requires exactly its specified bounty.

requestPortfolioPriceWithOperations(price, wethBudget, bounty, batch) funds a direct report and records ordered capital-ledger calls. The funding caller supplies the owner authority for every call; withdrawal recipients remain explicit in the signed calldata. A batch fixes accepted-price bounds, an expiry, a total gas allowance, and an array of operations containing calldata and individual gas limits. There is no fixed operation-count cap.

The ledger supports takeOver, takeOverWithBounds, takeOverAuctionBid, depositFor, depositAndSetHealthTarget, withdrawPrincipal, setHealthTarget, setCommitment, setCommitmentWithReport, claimEarnings, serveRetirement and materializeAuctionBid. Privileged accounting and fork entrypoints are excluded. Each call retains its ordinary owner, collateral, cohort, funding and reentrancy checks. A report-bound takeover may use zero for expectedAcceptedPriceEpoch to accept the settlement epoch; direct takeovers retain exact epoch checks. Funding can be deposited beforehand or by an earlier batch operation with the required REP approval.

The declared batch allowance must cover each individual limit plus 100,000 gas per operation. The OpenOracle callback budget is 4,000,000 gas plus that allowance; ordinary reports retain 4,000,000. After mandatory acceptance and portfolio checkpoints, the feed attempts every operation in order through executeReportOperation, which accepts only the canonical feed and authenticates a ledger self-call as the sponsor. Failed operations, including exhausted individual allowances and reverted auction materialization, roll back individually; later operations still run. Expired or out-of-range batches emit failed outcomes without executing their calls. ReportOperationAttempted(reportId, sponsor, operationIndex, success) records each outcome. Insufficient callback headroom reverts acceptance and earlier operations rather than publishing a price after skipping a promised attempt.

The batch runs inside its report's acceptance transaction regardless of who settles. It receives no priority over another report that settles first, no exclusive target reservation, and no reimbursement. Practical transaction and block gas limits bound execution. sponsorOperationReport(sponsor) identifies the latest batch report; reportOperationBatch(reportId) exposes its terms. Independent reports and ordinary recovery remain available.

Independent candidates

Reporting has no exclusive sponsor lane. Anyone may fund another candidate while earlier candidates are pending or the accepted price is still fresh. Disputing one candidate cannot reserve all reporting access.

Report sizing and correction incentives

The coordinator sizes each report so that correcting a price error of at least targetPriceErrorForDispute stays profitable after OpenOracle's fees and the modeled gas cost of one dispute multiplied by openOracleSecurityMultiplierBps. That multiplier is separate from a SecurityPool's backing multiplier, statoblastSecurityMultiplierBps.

A report can be corrected in either direction. The formula assumes the less profitable one, in which the true REP/ETH price is (1 + targetError) times the reported price, and models the correction as releasing the fraction (targetError - fees) / (1 + targetError) of the WETH position before gas. The required position is the multiplied gas cost divided by that fraction.

The minimum initial WETH position also has a floor of 1% of the portfolio’s aggregate exposure (aggregateExposureAttoEth()), and the same floor applies to the escalation halt:

reportAttoEth(gasPriceAttoEthPerGas) = ⌈ gasPriceAttoEthPerGas⋅gasUnitsForOneDispute⋅openOracleSecurityMultiplierBps ⋅(percentagePrecision+targetPriceErrorForDispute) 10000⋅(targetPriceErrorForDispute-protocolFee-feePercentage) ⌉ exposureReportAttoEth = ⌈aggregateExposureAttoEth100⌉ minimumToken1ReportAttoEth = reportAttoEth(initialReportPriorityFeeAttoEthPerGas) + max(reportAttoEth(block.basefee),exposureReportAttoEth) escalationHaltAttoEth = max(⌊initialWethReportAttoEth⋅escalationHaltMultiplierBps10000⌋,exposureReportAttoEth)

All amounts are in attoETH. percentagePrecision is 10,000,000, the denominator of targetPriceErrorForDispute, protocolFee, and feePercentage.

This is the ETH-exposure floor. The feed also requires REP-side funding of at least 1% of its REP exposure. At a proposed price, converting that REP minimum to ETH can increase the required initial WETH above this floor.

The coordinator sets initialWethReportAttoEth = max(minimumToken1ReportAttoEthForPrice(proposedRepPerEthPrice), requestedInitialAttoWeth), uses that value as OpenOracle's currentAmount1, and derives amount2 = ⌈initialWethReportAttoEth * proposedRepPerEthPrice / 1e18⌉ in the same transaction.

Formula inputs

Default report configuration comes from shared/statoblast/ts/initialReport/oracleInitialReport.ts and is copied into the shared feed configuration.

Formula input Current value Source
block.basefee Current request block EVM block context
initialReportPriorityFeeAttoEthPerGas Origin-pool parameter; the UI defaults to 10 nanoETH Immutable lineage configuration inherited by child pools
aggregateExposureAttoEth Current aggregate portfolio exposure Configured security pool
OPEN_INTEREST_DIVIDER 100 (a 1% floor) Coordinator constant
gasUnitsForOneDispute 300,000 gas Factory constructor; shared deployment configuration ORACLE_GAS_UNITS_FOR_ONE_DISPUTE
openOracleSecurityMultiplierBps 100,000 bps (10x) Factory constructor; shared deployment configuration OPEN_ORACLE_SECURITY_MULTIPLIER_BPS
targetPriceErrorForDispute 500,000 / 10,000,000 (5%) Factory constructor; shared deployment configuration ORACLE_TARGET_PRICE_ERROR_FOR_DISPUTE
protocolFee 100,000 / 10,000,000 (1%) Factory constructor; shared deployment configuration ORACLE_PROTOCOL_FEE
feePercentage (OpenOracle's reporter fee) 10,000 / 10,000,000 (0.1%) Factory constructor; shared deployment configuration ORACLE_FEE_PERCENTAGE
escalationHaltMultiplierBps 100,000 bps (10x) Factory constructor; shared deployment configuration ORACLE_ESCALATION_HALT_MULTIPLIER_BPS

Construction bounds and parameter effects

Coordinator construction requires:

  1. positive dispute gas units
  2. positive request gas: gasConsumedSettlement or gasConsumedOpenOracleReportPrice is nonzero
  3. a nonzero initialReportPriorityFeeAttoEthPerGas
  4. a target error no greater than 100%; shared feeds additionally require it to be strictly below 100%
  5. an OpenOracle security multiplier of at least 1x and at most type(uint256).max / (percentagePrecision + targetPriceErrorForDispute)
  6. combined OpenOracle fees below the target error
  7. a nonzero escalationHaltMultiplierBps
  8. a timestamp clock with dispute tracking (timeType and trackDisputes both true)
  9. maxSettlementBaseFeeMultiplierBps of at least 1x

Construction also bounds initialReportPriorityFeeAttoEthPerGas so that the priority-fee component of the minimum report, reportAttoEth(initialReportPriorityFeeAttoEthPerGas), does not exceed half of min(type(uint128).max, type(uint128).max × 10000 / escalationHaltMultiplierBps); a larger fee reverts with Initial report priority fee exceeds OpenOracle limits. OpenOraclePriceCoordinatorFactory stores the shared configuration without validating it, so an invalid configuration deploys the factory successfully and makes every later coordinator deployment revert.

At a 30 nanoETH base fee, a configured 10 nanoETH priority fee, and 100 WETH of aggregate exposure, the modeled gas cost of one dispute is 0.012 ETH, the minimum report is 3.230769230769230770 WETH, and the escalation halt is 32.307692307692307700 WETH.

Dynamic WETH report estimator

This calculator models the ETH-exposure floor, excluding the separate REP-inventory minimum. The deployment parameters and caller-selected amount are shown as adjustable inputs to make their effect explicit. For a deployed coordinator, the base fee and aggregate exposure can change from one request block to another.

Selected initial WETH3.2308 WETH
Fee boundfees below target error
Network costs
Pool security
Oracle fees
Coordinator policy
Report request
Initial-derived halt32.307692307692307700 WETH
Aggregate-exposure halt floor1.000000000000000000 WETH
Minimum token1 report3.230769230769230770 WETH
Escalation halt32.307692307692307700 WETH
Modeled dispute gas cost0.012000 ETH
Buffered gas target0.120000 ETH
Correction profit fraction after fees3.7143%

Settlement validation, rejection, and recovery

Low-level callback failure

OpenOracle invokes the price source through a low-level callback whose success is intentionally neither stored nor emitted. A failed callback does not automatically undo an otherwise valid OpenOracle settlement. A shared escrow authenticates OpenOracle and its own report ID; the feed accepts settlement only from that candidate’s registered escrow. Failure can leave an individually settled candidate unprocessed without blocking other candidates.

If the settlement transaction cannot retain enough gas headroom after the callback attempt, OpenOracle reverts settlement with InvalidGasLimit. In that case, the report has not settled and coordinator recovery is not yet available.

Price-source settlement validation

A callback that successfully enters the price source can still produce a rejected price. The price source emits PriceReportRejected and leaves the price cache unchanged when the first applicable condition below holds. A shared rejection records reportOutcome(reportId) = 2 and clears the latest-candidate getters only if they still name that report:

These checks establish only that the final WETH position meets the modeled security floor and that the callback data is structurally acceptable. They do not prove that the accepted price is externally correct, that an independent corrector exists, or that a correcting transaction will obtain inclusion.

Rejected-price cleanup

A rejected candidate leaves the accepted price unchanged. It cannot cancel other reports or reserve execution rights. Capital transactions remain subject to their own fresh state checks.

Recovering a settled report after callback failure

Anyone can recover a settled candidate through its report escrow. Shared feeds expose recoverReport(reportId) for any unprocessed settled candidate; recoverSettledPendingReport() is only a convenience for the latest ID. Shared recovery marks that candidate rejected and releases its escrow credits without accepting a price. Independently, anyone may call an escrow’s withdrawFunding() to deliver already-released credits to its original sponsor, including credits released by a dispute before settlement. Each escrow isolates those credits from other reports.

Liveness and exposure limits

Capital growth requires the accepted coverage or an independently funded proof. The feed does not impose an absolute deadline on an individual dispute game; shared candidates can proceed independently when another game remains disputed. See excluded guarantees EG03 and EG04.

Dispute escalation amounts

In this integration, WETH is the escalation variable. Before escalationHalt, OpenOracle requires min(⌊oldAmount1 × multiplier / 100⌋, escalationHalt). With the configured multiplier of 115, integer flooring leaves token1 amounts from one through six attoETH unchanged; seven attoETH is the first amount that grows. At or above the halt, each replacement instead requires oldAmount1 + 1, adding one attoETH of WETH.

OpenOracle parameters used

A source constant is fixed in the Solidity source. Deployment configuration is the shared configuration that the deployment passes to the coordinator factory, named by its constant in shared/statoblast/ts/initialReport/oracleInitialReport.ts; a deployed coordinator exposes each configured value through a public getter. The line under each value says where it is set.

Parameter Value and source Use in Statoblast
token1Address / token2Address WETH / REP
The factory's WETH and the pool universe's REP token
Defines the REP/ETH price pair used for security-pool solvency checks.
minimumToken1ReportAttoEth() See Report sizing and correction incentives and the estimator.
Derived per request
Minimum initial WETH position for a coordinator report.
OpenOracle initial currentAmount1 The greater of the minimum and the sponsor's requestedInitialAttoWeth
Derived per request
Initial WETH position; the sponsor may fund more than the minimum.
escalationHalt See Report sizing and correction incentives.
Derived per request
Ends multiplicative escalation; see Dispute escalation amounts.
settlerReward The committed bountyAttoEth; at least the request cost
Derived per request
Paid to the account that settles the report.
Sizing inputs: gasUnitsForOneDispute, openOracleSecurityMultiplierBps, targetPriceErrorForDispute, protocolFee, feePercentage, escalationHaltMultiplierBps, initialReportPriorityFeeAttoEthPerGas, OPEN_INTEREST_DIVIDER See Formula inputs. Size the report and the escalation halt. The two fees also set OpenOracle's dispute fee accounting.
getRequestPriceCostAttoEth() 101 attoETH Minimum public settlement bounty; sponsors pay their own gas.
callbackGasLimit 4,000,000 gas for ordinary reports. Operation batches add their declared gas allowance. Gas forwarded to the settlement callback. Settlement also needs enough surrounding gas to satisfy OpenOracle's callback headroom check.
maxSettlementBaseFeeMultiplierBps 30,000 bps (3x)
Deployment configuration ORACLE_MAX_SETTLEMENT_BASE_FEE_MULTIPLIER_BPS
Scales the request-block base fee plus configured priority fee into the settlement base-fee cap.
settlementTime 480 seconds
Deployment configuration ORACLE_SETTLEMENT_TIME
Report settlement delay on the timestamp clock.
disputeDelay 0
Deployment configuration ORACLE_DISPUTE_DELAY
Allows disputes immediately after each report and strictly before its settlement deadline. At the deadline, settlement is valid and a dispute is too late.
multiplier 115 (1.15x)
Deployment configuration ORACLE_MULTIPLIER
Growth of the WETH amount per dispute before the halt; see Dispute escalation amounts.
protocolFeeRecipient 0x000000000000000000000000000000000000dEaD
Deployment configuration ORACLE_PROTOCOL_FEE_RECIPIENT
Receives OpenOracle protocol fees for coordinator-created reports.
timeType / trackDisputes true / true
Deployment configuration; the constructor rejects any other value
Timestamps let the coordinator measure freshness from settlement eligibility; dispute history lets settlement validate the final report's recorded base fee.
callbackContract The candidate's SharedPoolReportEscrow.
Set when the report is created
Callbacks reconcile candidate funding and submit the settled price to the feed, including any sponsor-authorized operation batch.
PRICE_VALID_FOR_SECONDS / SEPOLIA_PRICE_VALID_FOR_SECONDS See Token pair and cached price.
Source constant
Keeper slack added to settlementTime by SharedPoolPriceFeed.priceValidityWindowSeconds().