HighLow binds one immutable Flare FTSOv2 source and one owner-rotatable oracle signer. FTSOv2 supplies every opening price and every timely closing price. The oracle has one explicit trusted fallback: after a missed 10-second live close window, it may type the nonzero closing price that settles the blocked round.
- The oracle submits
finalizeFromFtso(id)during[roundEnd, roundEnd + 10 seconds)and monitors confirmation, not only transaction submission. - A missed live close is resolved by an authorized operator calling
finalizeWithManualPrice(id, closePrice). Until that succeeds, funds remain unclaimable and no later round can start. - After a close exists, the oracle calls
startNextRound(id)at or afterroundEnd + 10 seconds. Failure leaves the closed round claimable but stops all later trading. - Operations monitor the selected FTSOv2 feed. FastUpdater exposes a batch submission timestamp, not proof that every selected feed changed in that submission.
- The owner is trusted with immediate economic configuration, pause, oracle rotation, automatic liquidity, and fee withdrawal authority. The owner cannot replace the immutable FTSOv2 source.
- Trading clients set meaningful
minSharesandminOutvalues. autoVLstays disabled unless its gross-volume input and selected bounds are intentionally accepted.
The timely close path reads live FTSOv2 and accepts no caller-supplied price:
round close = current FTSOv2 price during [roundEnd, roundEnd + 10s)
next open = current FTSOv2 price at startNextRound submission
The live adapter stores no historical samples. It rejects future timestamps, stale updater timestamps, feed-index mismatches, malformed return data, invalid decimals, zero, and overflow. HighLow applies the configured opening-to-closing deviation guard to the timely FTSOv2 close.
At roundEnd + 10 seconds, the live closing path permanently closes and the
manual oracle path opens. The manual path intentionally bypasses the deviation
guard so a genuine large price move cannot make recovery impossible. It records
MANUAL provenance on chain. The next opening remains FTSOv2-only.
If startNextRound registers an opening anchor during the second 10-second
interval, the anchor is held until the scheduled opening at roundEnd + 20 seconds. It can be up to 10 seconds old when trading opens, so its horizon to
the next close-window start is 100 to 110 seconds. The actual closing feed
publication may land during the following 10-second live window. A later
registration starts the round immediately and restores a 100-second scheduled
horizon.
There is no permissionless timeout, automatic VOID, skipped round, or stale anchor carry-forward. This is a deliberate liveness tradeoff: oracle failure can lock an unsettled round until the owner rotates the oracle or the oracle acts.
| ID | Finding | Current severity | Decision |
|---|---|---|---|
| H1 | A privileged reporter can choose a manual post-deadline result. | High, accepted trust assumption | Intentionally restored only after the live FTSOv2 window. Every manual close is marked on chain. |
| H2 | Missing required lifecycle calls can halt later rounds and can lock an unsettled round. | High, accepted operational risk | Deliberate hard gate. Deploy only with redundant automation, confirmation monitoring, oracle rotation, and a manual runbook. |
| H3 | The owner can replace settlement authority. | Medium, accepted governance power | The owner can rotate the operational oracle but cannot replace FTSOv2. |
| M1 | Reusing a closing price as the next opening changes the intended measurement interval. | Resolved | Closing and next opening are separate calls. The next opening always reads live FTSOv2. |
| M2 | A trader can sell and then buy through different addresses in one block around an unprotected victim sell. | Low | Accepted MEV risk. Clients must use minOut. |
| M3 | Optional auto-VL uses gross buy volume, so repeated buy and sell cycles can influence future depth. | Informational while disabled, Medium if enabled | Accepted. Keep disabled unless explicitly enabled and monitored. |
| L1 | Fixed-point LMSR rounding is not perfectly monotonic in extremely small dust states. | Low | Accepted numerical edge case. |
| L2 | sell and claim pay only msg.sender; a wallet that rejects native currency cannot redirect proceeds. |
Low | Accepted interface limitation. Supported wallets need a payable receive path. |
| L3 | Four-decimal reference prices can be too coarse for very low-priced feeds. | Low | Accepted listing constraint. Use feeds with adequate resolution. |
| I1 | Some owner setters do not emit dedicated change events. | Informational | Accepted. Operations read current state directly. |
| I2 | The inherited owner can renounce ownership. | Informational | Accepted governance responsibility. Production operations must not renounce accidentally. |
| I3 | Integer division can leave negligible claim dust. | Informational | Accepted accounting dust. |
- The oracle is operated by one key, one process, or one RPC endpoint.
- Confirmation monitoring or the manual close runbook is unavailable.
- The selected FTSOv2 feed is inactive, economically weak, or unsuitable for four-decimal storage.
- Frontends submit trades with zero slippage protection.
autoVLis enabled in production.- Owner or oracle authority is described as trustless.
Executable assumptions live under test/security/. End-to-end lifecycle
behavior is covered by test/integration/FtsoV2Finalization.t.sol, source
behavior by test/feeds/FtsoV2PriceSource.t.sol, and stateful accounting by
test/invariant/HighLowInvariant.t.sol.
Security contact: a16k-lab, info@a16.com.