SprawlSwap — Commodity Market
Per-resource batch call auctions quoted in ENERGY, with uniform clearing prices, burned fees, and permissionless settlement.
SprawlSwap — Commodity Market
Resources stream continuously, but they are produced where the geology says, not where the player needs them. SprawlSwap is the protocol-level commodity market that lets the Trader archetype exist: one canonical order book per resource token, quoted in ENERGY, cleared as a batch call auction at a game pace rather than a block pace.
The mechanic
- Each resource token gets exactly one canonical book, deployed by
SprawlSwapFactory. No duplicate venues, no liquidity fragmentation. - Time on a book is divided into epochs (default 1 hour, owner-tunable within 5 minutes – 7 days). Orders accumulate during an epoch; nothing matches mid-epoch.
placeBid(price, amount)escrows ENERGY at the limit price plus fee headroom.placeAsk(price, amount)escrows the resource. Prices are ENERGY wei per 1e18 resource units. Zero and dust orders are rejected.- Orders can be cancelled freely while their epoch is open, with immediate full refund of escrow.
- Once an epoch ends, anyone may call
settleEpoch(epochId). The contract computes the single uniform clearing price that maximizes matched volume; ties resolve to the midpoint of the best crossed bid and best crossed ask. The marginal price level fills pro-rata. - Every matched bid pays the clearing price (never more than its limit — the surplus is refunded); every matched ask receives the clearing price (never less than its limit).
- Orders are single-epoch: anything unmatched becomes refundable at settlement. There is no resting book between epochs.
- All proceeds and refunds follow the pull pattern: settlement only records balances; players withdraw with one
claim()call that transfers both their ENERGY and their resource in a single transaction.
Epoch clock
epochId = epochIdOffset + (now − epochAnchor) / epochDuration. Placing an order after an epoch has ended simply lands it in the next epoch — there is no dead window and no permissioned "open the next round" step. Changing the epoch duration re-anchors the clock and skips one epoch id; it is only allowed while the current epoch is empty, and every past epoch remains settleable by id because ids are strictly monotonic.
Fees
| Parameter | Default | Hard bound |
|---|---|---|
| protocolFeeBps (charged on ENERGY notional, both sides) | 1% | ≤ 10% |
| burnBps (share of fees burned to 0xdEaD) | 50% | ≤ 100% |
| settleRewardBps (share of fees to the settle caller, off the top) | 0% | ≤ 20% |
The fee for an epoch is snapshotted at the epoch's first order, so a mid-epoch fee change can never invalidate escrow already posted. The burned share is a permanent ENERGY sink: trading activity itself fights ENERGY inflation. The remainder routes to the treasury recipient.
Player-visible consequences
- Price discovery happens once per epoch, in public. Everyone trading a resource in an epoch gets the same price. There is no benefit to being first in the block, and nothing for a sandwich bot to bite.
- Bidding your true value is safe. You escrow at your limit but pay the clearing price; aggressive limits buy execution priority, not a worse price.
- Trading costs ENERGY twice: the notional and the fee. Markets are an ENERGY sink the same way actions are, so heavy commerce burns fuel.
- Liquidity is an appointment, not a stream. A thin resource trades when buyers and sellers show up in the same hour. Traders who reliably show up on both sides effectively become the market makers of the Sprawl.
- Anyone can be the keeper. Settlement is permissionless and may carry a fee-funded bounty, so bot operators can profit from keeping every book current.
Reasoning trace
Why a batch call auction, not an AMM? An AMM needs seeded inventory on both sides of every pair. The Sprawl has thousands of player-named resource tokens, most of them thin; permanent two-sided liquidity for each is unrealistic, and stale AMM pools are free money for snipers rather than for players. A call auction needs zero standing inventory — it monetizes coincidence of wants, which matches an economy where production is streamed and needs are periodic (maintenance baskets, army food).
Why not a continuous on-chain CLOB? Continuous matching on-chain pays gas per match, rewards latency, and invites MEV (front-running, sandwiching) — exactly the dominance vector a bot-friendly game must not sell. Batching to one clearing price per epoch removes ordering advantage within the epoch entirely and bounds settlement gas by construction. The game is turn-paced everywhere else (auctions, response windows, grace periods); the market should tick at game speed too.
Why ENERGY denomination? ENERGY is the abundant action fuel every player already holds and spends; pricing every resource in it gives the whole economy one numeraire instead of N² resource-to-resource pairs. It also makes the fee burn meaningful: commerce competes with actions for the same fuel, coupling market activity to the ENERGY sink that the rest of the design (movement costs, patent maintenance) already relies on.
Why single-epoch orders? Rollover means resting state: stale quotes that outlive the information they were based on, sniping of forgotten orders, and unbounded storage that settlement must walk. Expiring everything each epoch keeps state O(orders this epoch), makes "my escrow is locked at most one epoch" a hard guarantee, and matches how players actually trade in an hourly game — by showing up. Agents can re-quote each epoch trivially.
Why a uniform clearing price? Pay-your-bid auctions punish honesty and reward shading, which favors sophisticated bots over casual players. A uniform price is incentive-compatible enough that "bid what it's worth to you" is reasonable advice, and it produces one canonical, indexable price per resource per epoch — a public price feed the client UI and NPC systems can build on.
Anti-snowball and anti-grief safeguards
- Order caps: at most 128 bids and 128 asks per epoch. Settlement cost is bounded no matter what; a whale cannot make an epoch unsettleable. Cancelled orders still count toward the cap, so cap-stuffing is possible for one epoch at a time — but it costs escrow up front, resets every epoch, and a minimum order size is reserved as future tuning if dust-stuffing appears in practice.
- Fee bounds in code: 10% fee ceiling, 20% keeper ceiling — the owner cannot rug traders by setting confiscatory fees, and the epoch fee snapshot means escrowed orders are never retroactively repriced.
- Pull pattern everywhere: settlement never pushes tokens to traders, so no recipient can block or grief settlement by reverting on receive. The only direct transfers at settle go to fixed, known-good sinks (burn address, treasury, settle caller).
- Permissionless settle + keeper reward: no operator key is needed to keep markets running; if the protocol team disappears, any player bot can settle every epoch and is paid from fees for doing so.
- Per-epoch order expiry: there are no forgotten resting orders to snipe years later; maximum exposure of any escrow is one epoch plus claim time.
- Conservation by construction: buyer costs round up, seller proceeds round down; the at-most-a-few-wei difference accrues as inert dust in the book, so the contract can never owe more than it holds.
Implemented now vs future work
Implemented in contracts (SprawlSwapFactory, SprawlSwapBook, fully tested):
- per-resource canonical books, epoch clock, order placement/cancel with exact escrow math
- volume-maximizing uniform-price settlement with pro-rata marginal fills
- two-sided fees with burn/treasury split and optional settle-caller reward
- pull-pattern claims, indexer-ready events, owner config with hard bounds
Explicitly future work, not in contracts yet:
- maker/taker asymmetric fees
- order rollover / persistent resting book and market orders hitting it
- a minimum order size, if cap-stuffing griefing shows up on testnet
- NPC liquidity bot operation (an Earth-faction bot quoting baseline two-sided liquidity on staple resources)
- client UI wiring and the Ponder indexer views over the emitted events
Deployment status: SprawlSwap is deliberately not wired into the deploy scripts. It ships as code plus this spec until Fran/Ocean confirm whether it is in scope for the testnet launch.