FundPot
Ask AI
FundPot adds house money to the CURRENT week's prize pot without buying a single ticket. PERMISSIONLESS and CALLER-PAYS: the funder pulls from their own allowance, exactly as Buy does, so this realm gains no authority over anybody and any address can call it with its own money.
IT IS REALM-CALLABLE ON PURPOSE AND HAS NO IsUserCall GUARD. Do not add one for consistency with Buy. r/splash/arcade/duel calls this from realm code on every Collect — that is the arcade's rake, and gating it on an EOA would break the one mechanism that makes the duel and the raffle a single product. Buy's guard exists because a ticket is a claim on an outbound transfer (Resolve's pot, Refund's spend) and a realm's package-derived address may have no way to spend what arrives there; sponsorship creates no such claim at all — no ticket unit, no winning chance, no refundable record, see below — so a funder can never be the address a payout is pushed to and the defect Buy's guard closes cannot arise here. The asymmetry is deliberate and is stated at both ends.
WHY IT EXISTS. r/splash/arcade/duel sends its rake here: every coin flip makes this week's raffle prize bigger, which is what makes the two contracts one product rather than two features. It used to fund r/splash/game's yield and prize pots; that product is retired, and nothing in SPLASH holds money beyond a week any more.
IT CAN OPEN A WEEK, AND THEREFORE CAN PIN THAT WEEK'S BEACON ROUND. When the duel's rake arrives before anybody has bought a raffle ticket, this is the call that creates the week's record — and getOrCreateDraw pins Draw.Round there, once, for whichever entry point got there first (read pinOffsetRounds). A later Buy in the same week finds the record and never re-pins. The same beacon prerequisites as Buy therefore apply here, and there are now TWO: with no round ever published, and with no relay inside beacon.MaxEstimateStaleBlocks that raised the beacon's anchor, EstimatedLatestRound panics and THE SPONSORSHIP IS REFUSED.
AND THAT REFUSAL IS NO LONGER A CROSS-REALM HAZARD, WHICH IS WHY THE STALENESS BOUND COULD BE ADOPTED AT ALL. It used to be: r/splash/arcade/duel's Collect called this function IN THE SAME TRANSACTION as the winner's payout, so a refusal here reverted that payout — permanently, since VoidStale refuses a resolved duel. Collect now BOOKS its rake and duel.FlushPot delivers it, so a refusal here costs the flusher a reverted transaction and the booked balance is still there for the next attempt. Any caller can clear the refusal with one Publish of drand's current round. AUDIT-2026-09-28.md findings 12 and 14.
SPONSORSHIP BUYS NOTHING. d.tickets, d.ownerOf, d.ticketsOf and spendOf are all left alone: the funder gets no ticket unit, no winning chance, and no refundable claim. Only d.Sponsored and d.Pot move. A funder who never bought a ticket therefore cannot win the week they funded — ownerOfUnit can only ever name an address that appears in d.ownerOf, and nothing here writes to it.
THAT IS STILL TRUE OF THIS FUNCTION AFTER FINDING 15, AND IT IS THE REASON THE EARNED-ENTRY DOOR IS A SEPARATE FUNCTION RATHER THAN A PARAMETER HERE. FundPotWithEntries appends ticket weight for named holders and calls this function for the money; this function appends nothing for anybody, and every caller of it — including a realm, including the duel when it has no eligible holders to credit — still buys exactly nothing. Do not add holders to this signature: the guard that makes the other door safe would then have to be here, on the permissionless path the arcade's rake depends on.
WHY THE SEPARATE FIELD RATHER THAN JUST d.Pot += amount: read Draw.Sponsored. The one-line version is that d.Pot == sum(spendOf) is what makes Refund provably unable to overdraw, house money belongs to no buyer, and so the identity becomes d.Pot == sum(spendOf) + d.Sponsored rather than being quietly abandoned.
IT FUNDS THE LIVE WEEK ONLY, AND THERE IS NO COMMITTED-WEEK RACE HERE. Commit accepts only a week that is already over (week < currentWeek()), so the week currentWeek() names is uncommitted BY CONSTRUCTION — no concurrent commit can freeze it under a funder's feet, and money can never land in a pot whose winner is already being drawn. The refusals below are therefore defensive rather than reachable, and are kept for the same reason Buy keeps its own committed-week check: if the week this funds ever stops being "the one the clock is on", these are the lines that still refuse.
A SPONSORED WEEK WITH NO TICKETS IS NOT A DRAWABLE WEEK. Creating the week's record here is the same act Buy performs, and it does not make the week committable: Commit still panics on a zero ticket total, because there is no rollover and a drawless week must not exist. Such a week's sponsorship sits in the pot until somebody buys a ticket into it (the week is live, so they can) — and if the week ends with nobody having bought one, SweepDrawlessWeek registers that sponsorship for the next week to open (it names no destination itself — finding 28 — and it waits out a grace window first). THAT FUNCTION IS WHAT KEEPS THIS ONE SAFE: without it, funding a week that never sold a ticket stranded the money in a Draw that could never be committed, resolved or refunded. Refusing to create the record instead would mean the duel's rake bounced whenever it arrived before the week's first ticket sale, which would make settling a duel depend on somebody else's purchase.
Panics if amount is not positive, if the allowance is short, or — defensively — if the target week is already committed or has been abandoned into refund (there is nothing left to fund: its buyers are taking their money back).
Command
# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.
gnokey maketx call -pkgpath "gno.land/r/g1r4aw43kagaaquhegxw6xr346h9f2qu2ezf0jar/arcade/raffle/v3" -func "FundPot" -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "onyx-1" -remote "https://rpc.onyx.testnets.gno.land" ADDRESSgnokey query -remote "https://rpc.onyx.testnets.gno.land" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/g1r4aw43kagaaquhegxw6xr346h9f2qu2ezf0jar/arcade/raffle/v3" -func "FundPot" -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "onyx-1" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://rpc.onyx.testnets.gno.land" call.tx