Security & Audits
Hardened Contract Spec
Storage layout, invariants, and the exact solvency equation the contract must never break.
Verified contract
0x108D5CDC23123Fa97929Cf197151fb9dc29A5D93
Basescan-verified · solc 0.8.20 · optimizer 200 · paris
Money flow per ticket
text
F = floor(A x 400 / 10000) // 4% rake on the gross stake A
R = floor(F x 3000 / 10000) // referral cut, 30% of the rake
Ad = F - R // platform cut
N = A - F // credited to the option pool
pool.rakeAdmin += Ad // escrowed per market
poolReferral[poolId][kol] += R // escrowed per market
optionPool[poolId][opt] += N
totalNetPool += NNothing is withdrawable while a market is open. That is precisely what makes a 100% refund on cancellation arithmetically possible: the full gross stake is still sitting in the contract, untouched.
Solvency invariant
text
usdc.balanceOf(arena) >=
SUM(pool.totalNetPool) // every open + settled market
+ SUM(unpaid rake escrow of open pools)
+ accumulatedAdminFees // released only by settle()
+ SUM(poolReferral[settled pools]) // claimable only after settleVerified on a mainnet fork
A mixed-state run (10 markets: open, settled, cancelled) ended with balance 473.040002 USDC against 473.040000 USDC owed — a 2 wei surplus from integer rounding. Rounding always favours the contract, never the claimant.
Payout formula
text
payout = stake x totalNetPool / optionPool[winningOption]
// floor division, so SUM(payouts) <= totalNetPool always
// the residual dust (a few wei per market) is permanently lockedAccess control surface
| owner-only | createPool, seedPool, settle, cancelPool, withdrawAdminFees, setFeeVault, rescueERC20 |
| permissionless | bet, claimRewards, claimRefund, withdrawReferralFees, emergencyRefund |
| never rescueable | the USDC bet token (rescueERC20 reverts for it) |
| owner cannot bet | bet() reverts OwnerCannotBet — the oracle may not take positions from the owner address |