> ## Documentation Index
> Fetch the complete documentation index at: https://docs.counsel.markets/llms.txt
> Use this file to discover all available pages before exploring further.

# Structure des frais de protocole et calcul des gains sur counsel

> Comment counsel calcule les frais de protocole, le pool net, le gain par unité et les gains individuels, avec exemple chiffré et formules TypeScript.

counsel applique des frais forfaitaires uniques au pool brut avant de distribuer les gains. Il n'y a aucun frais d'entrée, aucun frais de retrait, ni aucune charge cachée. Comprendre le calcul des frais et des gains vous permet de vérifier votre rendement attendu avant de signer un pari, ou de construire un bot qui valorise les positions avec précision.

## Frais

Les frais de protocole sont forfaitaires, à **3 %** (`fee_rate: 0.03`), prélevés sur le pool brut total avant toute répartition. Les frais ne sont pas prélevés de manière sélective sur les mises restituées aux gagnants : ils sont déduits une seule fois sur l'ensemble du pool. Cela signifie que les mises du côté perdant contribuent à couvrir les frais au même titre que celles du côté gagnant.

En cas d'annulation, aucun frais n'est déduit. Chaque parieur récupère exactement sa mise initiale.

## Formules

```
T   = gross_pool            (sum of all stakes, all outcomes, in drops)
r   = fee_rate              (currently 0.03)

N   = T × (1 − r)           net pool after fee
P   = N / W                 payout per unit  (W = total staked on winning outcome)

payout_i = floor(s_i × N / W)   individual payout, floored to whole drops
```

Toute l'arithmétique sur le chemin monétaire est effectuée en **drops** (1 XRP = 1 000 000 drops) à l'aide de l'arithmétique entière, afin d'éliminer les erreurs d'arrondi en virgule flottante. Les gains individuels sont arrondis à l'inférieur au drop le plus proche ; le résidu d'arrondi (la poussière) est versé à la réserve de l'opérateur.

## Exemple chiffré

Un marché se clôture avec un total de 100 XRP, répartis en 60 XRP sur Yes et 40 XRP sur No. Taux de frais : 3 %.

|                        | Valeur               |
| ---------------------- | -------------------- |
| Pool brut (`T`)        | 100 XRP              |
| Frais (3 %)            | 3 XRP                |
| Pool net (`N`)         | **97 XRP**           |
| Pool Yes (`W`)         | 60 XRP               |
| Pool No (`W`)          | 40 XRP               |
| Gain/unité Yes (`N/W`) | 97 ÷ 60 = **1,617×** |
| Gain/unité No (`N/W`)  | 97 ÷ 40 = **2,425×** |

**Scénario : Yes l'emporte.** Un parieur ayant misé 20 XRP sur Yes reçoit :

```
payout_drops = floor(20,000,000 × 97,000,000 / 60,000,000)
             = floor(32,333,333.33…)
             = 32,333,333 drops  (32.333333 XRP)
```

L'arrondi à l'inférieur est appliqué au niveau du drop, pas au niveau du XRP. La poussière (le résidu sous le drop, cumulé sur l'ensemble des gagnants) est versée à l'opérateur.

## Implémentation TypeScript

Le code suivant est tiré directement de la bibliothèque de règlement de counsel (`src/lib/settlement/parimutuel.ts`). Tous les montants sont des drops de type `bigint`.

```typescript theme={null}
export interface FeeFraction {
  num: bigint;
  den: bigint;
}

/** Gross pool T = sum of all stakes across all outcomes. */
export function grossPool(stakes: bigint[]): bigint {
  return stakes.reduce((a, b) => a + b, 0n);
}

/**
 * Convert a decimal fee rate to an exact integer fraction.
 * Supports up to 6 decimal places; avoids floating-point on the money path.
 */
export function feeToFraction(feeRate: number): FeeFraction {
  const den = 1_000_000n;
  const num = BigInt(Math.round(feeRate * Number(den)));
  return { num, den };
}

/** N = floor(T × (den − num) / den) */
export function netPool(total: bigint, fee: FeeFraction): bigint {
  return (total * (fee.den - fee.num)) / fee.den;
}

/**
 * Indicative payout per unit for each outcome if it were to win.
 * Returns null for an outcome with zero stake (odds undefined).
 */
export function indicativePayoutPerUnit(
  stakes: bigint[],
  feeRate: number,
): (number | null)[] {
  const T = grossPool(stakes);
  const net = Number(T) * (1 - feeRate);
  return stakes.map((w) => (w === 0n ? null : net / Number(w)));
}

// Individual payout (integer arithmetic, floors to whole drops):
// payout_i = (s_i * N) / W
```

## Annulation : aucun frais prélevé

Lorsqu'un marché est annulé, aucun frais n'est appliqué. Le moteur de règlement rembourse chaque mise publique à sa valeur nominale : le nombre exact de drops envoyés est restitué sur le compte de l'expéditeur via un Payment XRP natif. Les mises d'amorçage du teneur de marché sont neutres pour la maison et ne sont pas remboursées.

`drops_in === drops_out` pour chaque parieur sur un marché annulé. Voir [Résolution](/concepts/resolution) pour les conditions qui déclenchent une annulation.

## Où trouver ces chiffres dans l'API

Le `fee_rate` et les chiffres de gain par résultat font partie de l'objet marché renvoyé par `GET /api/v1/markets/:id` :

```json theme={null}
{
  "id": "a1b2c3d4e5f60001",
  "fee_rate": 0.03,
  "total_xrp": 100,
  "outcomes": [
    {
      "index": 0,
      "label": "Yes",
      "destination_tag": 0,
      "pool_xrp": 60,
      "implied_prob": 0.6,
      "payout_per_unit": 1.617
    },
    {
      "index": 1,
      "label": "No",
      "destination_tag": 1,
      "pool_xrp": 40,
      "implied_prob": 0.4,
      "payout_per_unit": 2.425
    }
  ]
}
```

`payout_per_unit` vaut `null` pour tout résultat sans aucune mise (les cotes sont indéfinies tant qu'aucun pari n'a atterri de ce côté). Ces chiffres sont indicatifs jusqu'au passage de `bet_cutoff` ; voir [Pools parimutuels](/concepts/parimutuel) pour une explication complète de la manière dont les cotes évoluent avant la clôture.
