Technical documentation

How Proving Ground works

The mechanics, the on-chain design, the feed and escrow decisions, and the parts that are still unsolved. Everything here is a specification, not a description of running software.

1. The core model

An entrant never holds an asset. They hold points, and points move the way an asset moved.

Every entry starts with an identical pool of points, 10,000 in the current design. The entrant spreads those points across the assets listed for that competition. The program records an opening price for each asset when the window opens and a closing price when it expires. Each asset's percentage change over the window is applied to the points allocated to it. Points left unallocated do not move.

No order is placed on any market, no asset is custodied, and nothing the entrant does affects the price of anything. The market provides the returns; the contest provides the stakes.

Allocations are committed once, before the window opens, and locked for its duration. That is a deliberate constraint: it removes execution quality, latency and fills from the result, so the only thing being measured is the view the entrant took.

2. Scoring

Both formats share one formula.

final_points = Σ  allocation[i] × ( close[i] / open[i] )  +  unallocated

return_pct   = ( final_points − start_points ) / start_points

open[i] and close[i] are the oracle prices written to the competition account at the window boundaries. They are stored, not recomputed at read time, so a settlement is reproducible forever from chain state, and two parties reading the same account always agree on the result.

Prices are held as fixed-point integers with the exponent the oracle reports. Ratios are computed in a wide integer type and rounded once at the end, so the arithmetic is deterministic across clients rather than dependent on floating point.

The two formats differ only in what they do with final_points.

contest    → rank all entries by final_points, pay by finishing position
challenge  → return_pct ≥ target ? pay entry × multiple : pay nothing

3. Contests

A contest is relative. Many entrants share one window, one asset list and one prize pool, and the only thing that matters is where you finish.

Lifecycle

  1. Open. The contest account is created with its asset list, entry fee, entry deadline and window boundaries.
  2. Entry. Each entrant pays the fee into the escrow vault and receives an entry account. Fees accumulate into the prize pool.
  3. Allocation. Entrants commit an allocation vector before the entry deadline. After the deadline it cannot be changed.
  4. Window opens. Opening prices for every listed asset are written to the contest account in one instruction.
  5. Window closes. Closing prices are written the same way.
  6. Settlement. Final points are computed per entry, entries are ranked, and the pool is distributed by position. Anyone can call it.

Settlement being permissionless matters. If the operator disappears after the window closes, any entrant can still settle the contest and release the escrow, because every input needed is already on the contest account.

Prize distribution

The pool is the sum of entry fees, less a protocol fee, plus any yield earned on the escrow during the window. Distribution by position is a parameter of the contest rather than a constant, so a contest can pay the top three, the top ten percent, or on any other curve, as long as it is fixed at creation and visible before anyone enters.

4. Challenges

A challenge is absolute. There are no opponents. The entrant pays a fixed fee, picks how long the window runs and what return clears it, and either beats the number or does not.

Clearing the target pays a multiple of the entry from escrow. Missing it forfeits the entry. The multiple is quoted before the entrant allocates anything, and it is a property of the duration and target pair, not of what the entrant does afterwards.

Payout table

Target10 days20 days40 days
+5%1.8×1.5×1.3×
+10%3.2×2.4×1.9×
+20%6.0×4.2×3.0×

These numbers are placeholders used by the demo. They are shaped correctly, shorter windows and higher targets pay more, but they are not derived from a model. Pricing them properly is an open problem, see section 9.

Why all or nothing

A graduated payout would let an entrant hedge into a small guaranteed return and collect on volatility rather than on judgment. A single threshold forces a real decision: take enough risk to clear the target inside the window, or do not enter. The T-bill asset in the demo exists to make that visible. It cannot lose, and it also cannot get anyone to +20% in ten days.

5. Assets and feeds

Competitions list assets across three classes: equities, crypto, and real world assets such as metals and tokenised treasuries. Mixing them is the point. It lets one competition span instruments with volatility three orders of magnitude apart, which is what makes allocation a decision rather than a guess.

Oracle choice

Pyth is the primary source. It is Solana-native, it is pull-based so the program controls exactly when a price is recorded, and it carries equities, crypto, FX and metals in one feed set, which avoids stitching together several providers for a single asset list. Switchboard is the fallback for anything Pyth does not list.

RedStone is a reasonable oracle and strong on RWA coverage, but it is EVM-first, so on Solana it is the weaker fit. Chainlink's Solana presence is thinner than its EVM one. Neither is ruled out for specific feeds; neither is the default.

Only two prices per asset are ever recorded, at the window boundaries. The chart an entrant watches during a window is a convenience, not an input to settlement. That keeps the on-chain cost of a competition flat regardless of its length, and it removes any incentive to manipulate a price at a moment other than the two that count. It also concentrates all manipulation risk into those two moments, which is addressed in section 9.

Market hours

Equity feeds stop updating outside market hours while crypto keeps moving. Pyth publishes a trading status per feed, so the program records that status alongside each price. A window that expires into a closed market has to resolve somehow, and the candidates are: settle at the last known price with its status flag stored, roll the boundary forward to the next open, or refuse to create competitions whose boundaries can land outside market hours in the first place. The last is the most restrictive and the easiest to reason about, which makes it the likely starting point.

6. On-chain design

Anchor programs on Solana. Two account types carry all the state.

Competition account

One PDA per contest or challenge, seeded by a competition id. It holds the format, the asset list with its feed addresses, the entry fee, the window boundaries, the recorded open and close prices with their statuses, the escrow vault, and for challenges the target and multiple.

Entry account

One PDA per entrant per competition, seeded by competition id and wallet. It holds the committed allocation vector, the settled final points, and the payout status. Because the seed is deterministic, an entrant's full history across every competition is enumerable from chain state without an indexer.

Instructions

create_competition   config, asset list, window, fee, target
enter                pays fee into escrow, opens entry pda
commit_allocation    writes allocation vector, before entry deadline only
open_window          records opening price + status per asset
close_window         records closing price + status per asset
settle               computes points, ranks or compares, releases escrow
claim                entrant withdraws their settled payout

open_window, close_window and settle are permissionless and guarded by the clock rather than by an authority. Nobody, the operator included, can settle early, settle late in a way that changes the recorded prices, or skip an entry.

7. Escrow and yield

Entry fees sit in escrow for the length of a window. For a forty day challenge that is a meaningful amount of idle stablecoin. Routing it into a lending market earns yield that can top up prize pools, subsidise entry fees, or fund the protocol without taking a larger cut from entrants.

On Solana that means Kamino, MarginFi, Solend or Drift. Aave has no Solana deployment, so it is not an option here despite being the obvious reference point on EVM. Ethena is reachable cross-chain and pays more, but sUSDe carries funding-rate and depeg risk, which is a different kind of risk from lending and a poor fit for money that has to be paid out on a fixed date.

Constraints this has to respect

  • Escrow is other people's money. A loss at the yield venue lands on entrants, not on the protocol, unless the protocol explicitly backstops it.
  • Only a capped fraction of escrow is ever deployed, with the remainder liquid, so ordinary settlement never depends on a withdrawal succeeding.
  • The withdrawal must clear before the settlement deadline, not at it. A venue that pauses withdrawals must not be able to delay a payout.
  • The yield route is a parameter of the competition, visible before entry. Nobody gets opted into a risk they were not shown.

The conservative version of this feature earns less and is far easier to defend: deploy a capped share into a single blue-chip Solana money market, keep the rest liquid, and treat yield as a bonus to the pool rather than a number anyone is promised.

8. Agent access

Trading bots have nowhere cheap to prove themselves. A backtest is unfalsifiable, because it was written by the same person claiming the result. Live capital is an honest test but an expensive way to discover a strategy does not work. A contest with a fixed, small entry fee sits between the two: the result is adversarial and externally verifiable, and the downside is bounded and known in advance.

The barrier for an agent is not the trading, it is the paperwork. Signing up, holding an API key, and having a human on file are all things an autonomous agent handles badly. x402 removes all three by carrying payment in the HTTP request itself.

Entry flow

GET  /contests/current            → 200  contest id, assets, window, fee
POST /contests/{id}/enter         → 402  price + payment details
POST /contests/{id}/enter  (paid) → 200  entry pda, points, deadline
POST /contests/{id}/allocate      → 200  allocation committed on-chain
GET  /contests/{id}/result        → 200  final points, rank, settlement tx

Illustrative shape, not a shipped API. Nothing is running behind these routes.

Agent-only competitions

A competition can require that entries arrive over x402, producing fields where bots compete only against bots on identical feeds and identical scoring. That is a cleaner benchmark than mixing them with humans, whose entry timing and attention span are different in kind.

The output is the useful part. Every result an agent produces is a settled account on a public chain, keyed to a wallet its author controls. That is a track record anyone can verify and nobody can quietly revise, and it exposes nothing about the strategy that produced it.

9. Open problems

These are unsolved. Listing them is more useful than pretending otherwise.

Pricing the challenge multiple

The multiple has to be quoted before the entrant allocates, but the probability of clearing the target depends entirely on how much volatility they choose to take. An entrant who puts everything into the most volatile asset has a far better shot at +20% than one holding a balanced book, and the same quoted multiple covers both. Price it too generously and concentrated entries are profitable to spam. Price it too tightly and the product is not worth entering. A multiple that depends on the realised volatility of the chosen allocation would fix the asymmetry, but it cannot be quoted before the allocation exists.

Boundary manipulation

Compressing a window to two recorded prices makes settlement cheap and reproducible, and concentrates every incentive to manipulate a feed into those two instants. Thin assets are the exposure. A short time-averaged window at each boundary instead of a point reading is the obvious mitigation, at the cost of more oracle reads and a slightly less crisp definition of the price.

Market hours

Covered in section 5. Mixing assets that trade continuously with assets that stop every night is a real modelling problem, not a detail.

Yield risk

Covered in section 7. Any yield on escrow converts a payout obligation into a position that can lose money.

Sybil pressure on contests

In a prize pool ranked by finishing position, one participant entering many times with uncorrelated concentrated allocations improves their odds of taking a top place. Entry fees bound the attack rather than prevent it. Payout curves, entry caps per wallet, or both, are the levers, and none is free.

Regulatory shape

Fixed entry fees, all-or-nothing payouts and price-linked outcomes sit near regulated territory in several jurisdictions, and the fact that positions are simulated helps but does not settle the question. This needs a real opinion from someone qualified before mainnet, and the answer will differ by jurisdiction.

10. Roadmap

Pre-development. No programs are written, nothing is deployed to devnet or mainnet, and no funds are accepted.
  1. Now: mechanics design. Contest and challenge rules, the scoring formula, and the account layout. Validated by simulation, not by deployed code.
  2. Next: contest program. Anchor implementation of entry, allocation commit and settlement, tested against a local validator with mocked feeds.
  3. Then: feeds and devnet. Pyth integration, market-hours handling, and the first end-to-end contest settled publicly on devnet.
  4. Later: challenges and escrow yield. Target-based challenges, multiple pricing, and a yield route with the controls in section 7. Audit before any mainnet funds.
  5. Later: agent league. The x402 gateway and agent-only contests, once the human path is settled and proven.

Points are contest scoring units. They are not securities, they confer no ownership of any asset, and no order is placed on any market. Nothing described here is live.