Skip to main content
A counsel market lives entirely on the XRP Ledger. Its definition is a memo, its stakes are tagged Payments into a pool account, its resolution is an on-chain memo referencing an oracle value or a signed committee decision, and its payouts are native Payments back to winners. Every step is replayable from the ledger. There is no authoritative database off-chain: the ledger is the registry, the pool, and the audit trail.
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 a counsel/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:
DestinationTag
integer
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.
SourceTag
integer
counsel’s attribution tag, supplied by the UI or SDK. This credits the bet to counsel for leaderboard and attribution purposes.
Amount
string
Your stake in XRP drops (1 XRP = 1,000,000 drops).
The Payment also carries a JSON memo (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.
{
  "TransactionType": "Payment",
  "Account":         "<your address>",
  "Destination":     "<pool account>",
  "Amount":          "5000000",
  "DestinationTag":  0,
  "SourceTag":       2606220005,
  "Memos": [
    {
      "Memo": {
        "MemoType":   "636F756E73656C2F6265742F7631",
        "MemoFormat": "6170706C69636174696F6E2F6A736F6E",
        "MemoData":   "<hex-encoded JSON payload>"
      }
    }
  ]
}

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 outcome k, the displayed figures are:
FieldFormula
implied_proboutcome_drops / total_drops
payout_per_unittotal_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.
1

Oracle publishes price

An XLS-47 PriceOracle object on the XRP Ledger holds the latest published price for the asset pair.
2

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.
3

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).
4

Outcome published on-chain

The resolved outcome and the oracle value read are written as a counsel/resolution/v1 memo to the registry. This is the permanent, auditable record of the resolution.

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.
1

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.
2

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.
3

Committee finalization

If the dispute window closes with no challenge, the operator settles. If a dispute was filed, the multisig committee (a SignerList on the pool account) finalizes by supermajority signature. Every signature and the final outcome are published on-chain.

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.
net_pool = total_drops * (1 - fee_rate)
payout_per_unit = net_pool / winning_outcome_drops
payout_i = floor(stake_i * payout_per_unit)
Each payout is sent as an individual committee-multisigned native XRP Payment with a 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).
On a void, every staker receives a full refund Payment. No fee is deducted.

Full lifecycle

1

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.
2

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.
3

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.
4

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.
5

Payouts

The pro-rata split is computed and sent as committee-multisigned individual XRP Payments to each winner. Voided markets receive full refund Payments instead, with no fee.