Skip to main content
A place call reverts unless it clears all of these gates. Quote them client-side before sending the transaction - every value below is readable on-chain.

Constraint table

Liability is the maximum the pool might have to pay: Strike W, Range P_max, TieredBetter max(payouts), Shuffle sum of the K largest rungs. It is reserved against the bankroll at place time and released at settle. Kelly’s payoutLo is 0 for Strike, P_min for Range, min(payouts) for TieredBetter, and the sum of the K smallest rungs for Shuffle. The cap is non-binding when payoutLo ≥ stake.

The effective multiplier

effectiveMaxMultiplierBps() is a live gate that scales linearly with bankroll utilization:
Formula
A 100× Strike that quotes fine on an idle pool can revert minutes later when other bets fill the liability budget. Re-read effectiveMaxMultiplierBps() (or consume the BankrollSync event, which carries all the precomputed caps) right before placing.

TieredBetter mass snapping

The contract checks the TieredBetter EV identity in exact integer math - a float-solved probability set almost never lands on it after rounding to WAD. The reference client rounds masses with a largest-remainder allocation, then transfers single units of mass between buckets until the on-chain check passes (see snapMassToChain in the web app’s tieredBetterQuotes). If you build TieredBetter args yourself, do the same: quote with the exact contract formula, and adjust masses (not payouts) until Σ massWad × payouts / WAD == EV × stake. Preview with validateTieredBetter before sending. Shuffle has no mass array - snap payouts so Σ payouts · K == N · EV × stake and preview with validateShuffle.

expectedCommitId freshness

Every place call pins the epoch it bets under. Read currentCommitId() immediately before sending; if the keeper rotates the epoch between your read and your transaction, the call reverts CommitMismatch - just re-read and retry. There is no max-age gate on an open epoch, so an open epoch never goes “stale” on its own.
All caps in one read: subscribe to the BankrollSync event, which emits availableBankroll, effectiveMaxMultiplierBps, maxBetCap, and maxBetLiabilityCap after every place, settle, and stake movement - no eth_call polling needed. See Events.