← Writing

Beyond the Bet: Auditing a Prediction Market on Sui Move

A month of field notes from a private review of a Sui Move prediction market: what the money flow looks like, where oracle and PTB boundaries get dangerous, and why the most important bugs live between components.

0xTheBlackPanther Aug 2026 8 min read Prediction Markets, Sui, Move, Security

I recently finished a one-month private security review of a prediction-market system built in Move on Sui, including its signed external oracle integration. I cannot publish client names, private traces, or exact exploit recipes. I can share the review habits and general lessons because they apply to almost every on-chain prediction market.

The first surprise was how little the protocol looked like a simple betting app. It behaved more like a small bank, a pricing engine, a settlement ledger, and an asynchronous liquidity pool running inside one state machine.

The useful mental model: traders buy claims, LPs provide the balance sheet, oracles define the mark, and settlement turns that mark into a final cash obligation.

Start With the Money, Not the Functions

Before reading individual entry points, I drew the full cash flow:

The prediction-market cash flow: Trader → premium and fees → market cash
LP → queued deposit or withdrawal → frozen NAV mark
Settlement → terminal liability → winner redemption
Surplus → protocol accounting and LP equity

That map immediately creates the important questions: does every token movement have a matching ledger update? Is cash reserved before it is released? Does an LP receive shares based on the same economic value used by settlement? Can a request, refund, or cleanup path skip one side of the accounting?

The central invariant is simple to say and hard to preserve:

// the accounting question
cash held + valid obligations = what the protocol says it owns

Most serious DeFi accounting bugs are different views of that equation disagreeing for one transaction, one market, or one timing window.

Three Boundaries Where the Interesting Bugs Hide

1. The oracle is part of the state machine

The system used more than one kind of price input. One feed supplied a model-based live price; another supplied the exact terminal observation used at settlement. That separation is sensible, but it means every consumer must know which timestamp, source, and value it is actually trusting.

The review repeatedly came back to four oracle questions:

  1. Was the value authenticated, or merely well-formed?
  2. Is freshness measured from generation time, publication time, or transaction time?
  3. Can a value written earlier in the same PTB be reused after the state changes?
  4. Does a normalized value preserve the provenance of the raw observation?

One important class of issue came from reading two valid snapshots in one programmable transaction. The final fix records the writer transaction digest on every relevant oracle read and refuses to build a live pricing snapshot from an observation written by the same PTB. The broader lesson is stronger than “check the timestamp”: provenance is a security property.

2. Fixed-point shortcuts can become economic decisions

Pricing code often contains fast paths for extreme values. They look harmless until the result feeds mint admission, liquidation, NAV, and settlement accounting at the same time.

A ratio was once rounded into fixed-point form before its logarithm was evaluated. At the tails, that could discard the information the model needed. The safer implementation computes log-moneyness as:

// stable log-moneyness
k = ln(strike) - ln(forward)

That change matters because it fixes the arithmetic at its source instead of rejecting legitimate model inputs just to make an unsafe shortcut appear sound. A useful audit rule emerged: whenever a math shortcut returns an exact 0% or 100%, prove that the result is independent of every other input it skips.

3. Sui composition changes the threat model

Sui's object model and Programmable Transaction Blocks make composition a first-class security boundary. A caller can sequence oracle writes, snapshot creation, minting, redemption, and queue actions in one atomic transaction. Dynamic fields also mean the state of a protocol is larger than the parent struct suggests.

For each public flow, I traced:

The Sui review loop: readvalidatemutatepayclean up

Then I permuted the calls inside a PTB and across separate transactions. A check that is correct in isolation may be too late after another command has changed the shared object. This is the Move version of a stale-snapshot bug: there is no EVM-style reentrancy, but there is still same-transaction state composition.

What the Review Taught Me About “Bugs”

Not every surprising behavior is a fund-loss vulnerability. Some findings turned out to be bounded liveness concerns: an operation could wait, a cleanup path could be expensive, or a queue could require a keeper. Others were accepted design decisions with explicit economic trade-offs.

The discipline was to separate three questions:

  1. Can a user cause it? A permissionless call is not automatically exploitable.
  2. Who loses value? A reverted transaction, delayed cleanup, and drained LP reserve are very different impacts.
  3. Is the behavior documented and intended? If yes, it may be a design risk rather than a reportable defect.

This distinction improved the audit. It kept accepted operational trade-offs out of the critical queue while allowing genuine accounting and pricing inconsistencies to receive the attention they deserved.

Fix Review Is a Second Audit

The work did not end when a patch appeared. The most valuable fix-review questions were:

One arithmetic issue first received a bounds-based workaround, then a better source-level fix replaced it. A leverage-related risk was ultimately removed by removing the feature itself, which required follow-up cleanup across contracts and off-chain surfaces. These are good reminders that a patch can be correct while still being a protocol migration event.

A Compact Checklist for Prediction-Market Audits

// prediction-market audit checklist
1. Map every cash balance and logical liability.
2. Separate live pricing from exact settlement pricing.
3. Bind every oracle value to its source, timestamp, and writer.
4. Test PTB orderings, not only individual entry points.
5. Compare mint, redeem, settle, keeper, and cleanup paths.
6. Exercise rounding, saturation, empty state, and boundary values.
7. Read known issues before writing a new one.
8. Re-run the invariant after every fix.

Final Takeaway

The deepest lesson from this review was not about a particular oracle or a particular Move function. It was about composition. A price can be mathematically correct but used with the wrong timestamp. A queue can be fair but still create liveness pressure. A reserve can be locally backed while the global LP view is wrong. A PTB can make two individually valid operations economically inconsistent.

Prediction markets are not just betting interfaces. They are custody systems with a live pricing surface, a settlement engine, and an LP balance sheet. The bugs live at the handoffs.

Context: Generalized notes from a private one-month Sui Move prediction-market review
Focus: Pricing, signed oracles, settlement, NAV, LP queues, and PTB composition
Disclosure: Client names, private traces, and sensitive exploit details intentionally omitted
Follow: @thepantherplus

If any statement here is inaccurate or becomes outdated, please reach out on X so I can correct it.