Penalty Shootout
Pick your spot, beat the keeper, bank the win streak. Every goal compounds your multiplier, every dive is a fresh Chainlink VRF draw, and you decide when to walk away. Fully onchain.
How it works
Overtime Penalty Shootout is a streak game: one stake, as many kicks as you dare.
You pick a difficulty (Amateur, Pro or World Class), choose where to aim, and take the first kick. Placing the bet and taking the first kick happen in one transaction
The contract requests a random word from Chainlink VRF. The keeper's dive is derived from it:
randomWord % zones, one zone out of the difficulty's totalIf the keeper dives anywhere other than where you aimed, it's a goal and your running multiplier grows by the difficulty's factor. If the keeper dives to your zone, it's a save: the run ends and the stake is lost
After every goal you choose again: take another kick (at any difficulty) or cash out to take
stake × current multiplierThe run continues until you cash out, the keeper saves, or no difficulty fits under the multiplier cap
Where you aim does not change your odds. The keeper covers exactly one zone, chosen uniformly at random, so your chance of scoring is simply the open zones over the total. Your aim is written to the contract in the same transaction that requests the randomness, before the random word exists, so neither your shot nor the keeper's dive can react to the other.
Difficulty levels
Each difficulty narrows the goal. The keeper always covers one zone.
Amateur
5
4
80% (4 in 5)
1.225×
Pro
3
2
66.7% (2 in 3)
1.47×
World Class
2
1
50% (1 in 2)
1.96×
You can switch difficulty between kicks. Bank a few Amateur goals and finish at World Class, or open big and play it safe once the multiplier is worth protecting. The game is fixed for the whole run; only the difficulty and your aim change from kick to kick.
The multiplier
Every goal multiplies your running total by the difficulty's factor:
That's the entire pricing model. It makes chance to score × factor = 1 − houseEdge for every difficulty, so each kick carries exactly the same house edge whichever one you pick. At the default 2% edge that's 1.225×, 1.47× and 1.96×. Players never supply odds: a kick is a difficulty and an aim, and the contract looks the odds up and derives the factor itself.
Goals compound:
1
1.225×
1.47×
1.96×
2
1.50×
2.16×
3.84×
3
1.84×
3.18×
7.53×
4
2.25×
4.67×
14.76×
5
2.76×
6.86×
28.93×
6
3.38×
10.09×
56.69×
Most before cap
22 goals, 86.89×
11 goals, 69.26×
6 goals, 56.69×
Mixing difficulties gets closer to the cap: the highest reachable multiplier is about 99×.
Because the edge applies to every kick, it compounds across a run. A run you cash out after n goals returns 0.98ⁿ of the stake on average at the 2% edge (about 90.4% after 5 goals, whatever the difficulty). The harder difficulties reach a given multiplier in fewer kicks, so they pay less total edge getting there, in exchange for a much bigger chance of an early save.
The cap. The default multiplier cap is 100×. A kick whose factor would push the multiplier past the cap is rejected, not trimmed: payouts are never silently truncated. Near the cap only the difficulties that still fit are playable (playableTiers), and once none fit, the only move left is to cash out. The house edge and the cap are both snapshotted when you place the bet, so a later parameter change can never alter a run that's already live.
Cashing out
This is the whole game. After any goal your multiplier is locked in as long as you stop. The moment you kick again, you're risking the entire accumulated amount on the next dive.
Cash out → you receive
stake × current multiplier, the run resolves, doneKick again → a goal grows the multiplier; a save loses everything
There is no partial cash out and no insurance. Reaching the cap does not cash out for you either: winnings are paid only in the cash out transaction, never inside the VRF callback.
Before each kick, the contract checks that the treasury can cover what that kick would owe if you score. If it can't, the kick is rejected before any randomness is requested, and your run stays exactly where it was, cashable at its current multiplier.
Runs don't expire. If a run sits idle after a goal for longer than the core's cancelTimeout, the resolver can settle it for you with adminCashout, which pays exactly what a cash out would: stake × current multiplier. It cannot pay less.
Limits
Minimum bet
3 USD (configurable per game via core)
Maximum bet
Bounded by max profit: stake × (cap − 1) ≤ maxProfitUsd. At a 2,000 USD max profit and the 100× cap, about ~ 20 USD
House edge
2% per kick
Multiplier per goal
1.225× / 1.47× / 1.96× at 2% edge
Multiplier cap
100× default, snapshotted per bet
Max kicks per run
200
Push
None: every kick is a goal or a save
Idle run
Resolver may settle it after cancelTimeout at the full stake × current multiplier
Cancellation
Admin/resolver only, intended for a stalled VRF request; refunds original stake, forfeits accumulated multiplier
If the game is paused while you're mid-run, Cash Out is available again as soon as it's unpaused. The resolver's adminCashout is not pause-gated and still pays the full multiplier.
Supported collaterals: USDC, WETH, $OVER. Free bets supported via the isFreeBet flag on placeBet. On a lost real-money run, the referrer's share is paid automatically in the transaction that settles the save.
User guide
1. Open Penalty Shootout
Select Penalty Shootout from the casino lobby. Set your stake and collateral.
2. Pick a difficulty
Choose Amateur, Pro or World Class. The panel shows the payout on a first goal.
3. Aim and shoot
Pick your spot and hit Take the Kick. This places the bet and takes the first kick in a single transaction.
4. Goal or save
When the VRF callback arrives, the keeper dives. Goal: your multiplier ticks up and it's your turn again. Save: the run is over.
5. Shoot again or cash out
Keep the difficulty or change it, and kick again to push the multiplier higher. Or hit Cash Out to bank stake × multiplier.
6. Resolution
Cashing out, or a save, resolves the bet. Your full run is stored onchain and shown in your history: the difficulty of every kick, its factor, where the keeper dived, the result, and your multiplier after each one.
Onchain reference
Penalty Shootout runs on StreakGame, a streak engine on the shared CasinoCoreV2 treasury. Games on the engine are registered modes, each with a fixed set of difficulty tiers validated when they're published. Read getModes() for the live list.
Start a run (bet + first kick)
placeBet(collateral, amount, referrer, modeId, tierIdx, choice, isFreeBet)
Next kick
playRound(betId, tierIdx, choice)
Cash out
cashout(betId)
Difficulties still playable
playableTiers(betId)
Kick-by-kick history
getBetRounds(betId)
Factor for a difficulty
factorForTierE18(modeId, tierIdx)
Penalty Shootout is modeId = 1. tierIdx: 0 Amateur, 1 Pro, 2 World Class. choice is the zone you aim at, from 0 to zones − 1.
Why this matters
A streak game is the easiest game in a casino to rig. The whole product is the question of whether to shoot one more time, and on a centralized site nothing stops the server from making the keeper a little better at reading you exactly when your multiplier gets big. You'd never see it happen.
On Overtime, the keeper can't read you. Each dive comes from a fresh Chainlink VRF request that doesn't exist until your aim is committed onchain. The odds are zones you can count, the factor is a published formula, the house edge is a public variable locked into your bet when you place it, and every kick of every run is reconstructable from the chain. The only thing deciding whether you score is the dive. Which is the entire point.
Last updated

