counsel is custodial-transparent, not trustless. Pools sit in per-market accounts secured by a multisig SignerList with the master key disabled, so no single key can move funds. Everything is on-chain and independently recomputable.
1. Create a market (on-chain)
An operator writes acounsel/market/v1 JSON memo on a Payment to the registry account. The definition includes the pool account, the outcomes, the family (A or B), the resolution parameters, and the void policy. There is no smart contract and no deploy step: a market is a record on the ledger.
The pool account is a per-market XRPL account. Its master key is disabled and a multisig SignerList controls it, so stakes can only leave the pool through committee-signed Payments.
2. Bet via a tagged XRP Payment
To place a bet, you send a native XRP Payment to the market’s pool account with two tags set:The integer index of your chosen outcome (for example
0 for the first outcome, 1 for the second). This is how the pool account knows which outcome pool your stake belongs to.counsel’s attribution tag, supplied by the UI or SDK. This credits the bet to counsel for leaderboard and attribution purposes.
Your stake in XRP drops (1 XRP = 1,000,000 drops).
counsel/bet/v1) recording the market ID, outcome index, and outcome label, so every bet is independently readable on-chain.
You sign this Payment in your own wallet (Xaman, GemWallet, Crossmark, or a bot key). counsel constructs the unsigned transaction and returns it. It never signs on your behalf and never holds a key. This is non-custodial.
3. The live tote board
The moment a bet lands on-chain, counsel reads it from the ledger and recomputes the odds for every outcome. The tote board updates in real time. For each outcomek, the displayed figures are:
| Field | Formula |
|---|---|
implied_prob | outcome_drops / total_drops |
payout_per_unit | total_drops * (1 - fee_rate) / outcome_drops |
payout_per_unit is the indicative XRP returned per 1 XRP staked if that outcome wins, after the fee.
These figures are indicative while the market is open. Because counsel is a true parimutuel market, every subsequent stake shifts the line. The split is final at bet_cutoff, set by the pool state at close. There is no way to lock a price seen before close.
4. Resolve
Family A: crypto price (oracle)
Crypto-price markets resolve automatically against the native XLS-47 price oracle. No human is in the settlement loop.Oracle publishes price
An XLS-47
PriceOracle object on the XRP Ledger holds the latest published price for the asset pair.Bets close at bet_cutoff
At
bet_cutoff, the pool is frozen. Any Payment arriving at or after this timestamp is not counted as a stake. The cut-off is enforced from the ledger timestamp, not just the UI.Oracle value read at resolution time
counsel reads the oracle’s latest value from the ledger and checks its freshness window. If the oracle value is stale, the market voids (see below).
Family B: real world (proposal, dispute, committee)
Real-world markets (sports results, governance outcomes, macro events) resolve by an operator-proposed outcome, a bonded dispute window, and a multisig committee finalization.Operator posts a proposal on-chain
At resolution time, the operator publishes a
counsel/proposal/v1 memo naming the proposed outcome and supporting evidence. This transaction starts the dispute clock.Dispute window opens
During the bonded dispute window, any XRPL account can challenge the proposal by posting a bond on-chain. The bond amount matches the operator’s bond.
5. Pay out
Both families pay out the same way. The fee is a flat 3% (fee_rate, typically 0.03) taken from the whole gross pool before the split, never selectively on winners. The net pool is then divided across the winning side pro rata to each winner’s stake.
counsel/payout/v1 memo recording the market ID, outcome, and split. Anyone can recompute the split from the ledger and verify every payout. Rounding residue from integer drop arithmetic accrues to the operator reserve rather than inflating any single payout.
Void and refund (degenerate pools)
A market is voided and fully refunded, with no fee, when the pool is degenerate:One-sided pool
Only one outcome received stake, so there is no opposing side to pay.
No winner
No outcome can be declared a winner under the market definition.
Cancelled event
The underlying event was cancelled, postponed, or tied.
Stale oracle
No fresh oracle value exists within the freshness window (Family A).
Full lifecycle
Market created on-chain
Operator writes a
counsel/market/v1 memo on a Payment to the registry account, defining the pool account, outcomes, family, resolution parameters, and void policy.Betting open
Users send tagged XRP Payments to the pool account. counsel reads the pool account’s transaction history from the ledger and maintains live outcome pools and odds.
bet_cutoff reached
The pool freezes. Any stake arriving at or after the cut-off timestamp is not counted. The final odds line is now set.
Resolution
Family A: counsel reads the XLS-47 oracle and publishes the outcome on-chain. Family B: operator posts a proposal, the dispute window runs, and the committee multisigns the final outcome.