> For the complete documentation index, see [llms.txt](https://countertrade.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://countertrade.gitbook.io/docs/transparency/check-a-result.md).

# Check a result

Confirm a downloaded settlement report is the one committed on-chain, check its trade evidence, and recompute the ranks and payouts by hand.

You can check a settled room's result without trusting the page that shows it. Confirm that the settlement report is the exact document committed on-chain, then redo the ranking and the payout split yourself.

## Check it in your browser

Open `/verify/` followed by the room's id in the app, for example from the QR code on [your battle statement](/docs/transparency/your-battle-statement.md). The page **Check this result** downloads the room's report and trade evidence, reads the escrow's record for the room through the blockchain node (RPC) the CounterTrade app is set up with, and runs each check on this page in your browser:

* The report is for this room, on CounterTrade's network and one of its escrow contracts, and its hash, payout root, referral root and totals match the escrow's record.
* Both trade roots, rebuilt from the trade evidence rows (v8 reports).
* Conservation, ranks, and the payout amounts for `winner_takes_all` and `top_3_60_30_10` rooms.

Each check shows **Pass**, **Fail**, **Unanchored** or **Not checked**. **Unanchored** means the report agrees with itself there, but isn't proven to be the document the escrow anchored, for example because the escrow couldn't be read. Select **Read the escrow again** to retry. **Not checked** means the check couldn't run, for example a payout split that depends on room settings the report doesn't carry. A private room publishes no report, so the page has nothing to check.

The page is a convenience, served by CounterTrade like the report itself, and it reads the chain through CounterTrade's node. To rely on no CounterTrade code or node at all, do the same checks by hand below.

## Before you start

* You have the room's report, and for a v8 report its trade evidence, saved unchanged. See [Download the report and trade evidence](/docs/transparency/download-the-evidence.md).
* You have a tool that computes **keccak-256** over a file's bytes, such as Foundry's `cast keccak` or any Ethereum library. A sha-256 tool gives a different number.
* You have the room's settlement transaction. It is linked as **Settlement** on the room page, and as **Settlement tx** in a room's **Settlement** card.

## What the report contains

The report is one JSON document. The parts you need:

| Block              | What it holds                                                                                                                                   |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `room`             | The on-chain room id (`contract_room_id`), the chain, the escrow and token addresses, the room type and its `prize_distribution`                |
| `participants`     | One row per player: `wallet_address`, `rank`, `final_equity`, `final_roi_bps` (ROI in basis points: 1000 is 10%), and `team_side` in a 5v5 room |
| `payouts`          | One row per paid place: `leaf_index`, `rank`, `recipient_address`, `amount`                                                                     |
| `referral_payouts` | Referral rewards paid from the fee: `leaf_index`, `recipient_address`, `amount`                                                                 |
| `accounting`       | `escrowed_amount`, `total_payout`, `total_referral`, `platform_fee`, and the rounding rules (`remainder_policy`)                                |
| `hashes`           | The payout and referral Merkle roots, and fingerprints of the trade log, price data and final results                                           |
| `trade_evidence`   | v8 only: `fill_count` and `close_mark_count`, the number of rows the trade evidence file must hold                                              |

Every amount is a whole number in the token's smallest unit. USDC has 6 decimals, so `59400000` is 59.40 USDC.

## Confirm it is the committed report

1. Compute the keccak-256 hash of the downloaded report's bytes.
2. Open the room's settlement transaction on the block explorer and find its `SettlementSubmitted` event.
3. Compare your hash with the event's `tradingReportHash`. They must be identical.

If they match, this file is the document CounterTrade signed when it settled the room, and it can't have been changed since. In the same event, `payoutMerkleRoot` must equal `hashes.payout_merkle_root` in the file, and `totalPayout` must equal `accounting.total_payout`.

You can also read the anchor straight from the escrow. On the block explorer for the report's chain, open the escrow address named in the report and read `getSettlement` with `room.contract_room_id`. The **third field** is `tradingReportHash`. Production escrow v0.13 is on **Base mainnet (chain 8453)**; use the report's chain and escrow to identify the correct contract.

## Check the trade evidence (v8 reports)

The trade evidence file holds the room's fills in `fills` and its platform close marks in `close_marks`, identified by wallet address. The report signs two roots over them: fills hash to `hashes.trade_log_hash`, and close marks hash to `hashes.price_data_hash`.

Once the report matches its on-chain anchor, you can check that the evidence file belongs to it:

1. The file's `room_id` must equal the report's `room.room_id`, and its `report_schema_version` must be `8`.
2. The file's `trade_log_hash` and `price_data_hash` must equal the report's `hashes.trade_log_hash` and `hashes.price_data_hash`.
3. The number of rows in `fills` must equal the report's `trade_evidence.fill_count`, and the number in `close_marks` must equal `trade_evidence.close_mark_count`.
4. Every `wallet_address` in the file must be a wallet from the report's `participants`, or a seat that was refunded.

Then find a wallet in `fills` and `close_marks` to inspect its trades. These checks tie the file to the signed report. To show that the rows themselves are the ones signed, rebuild the two roots from them as described in [Trade evidence encoding](/docs/transparency/trade-evidence-encoding.md): each must equal the report's root. Even then, the evidence shows which trades the platform recorded. It doesn't independently prove that an execution price matched the market.

## Recompute the ranks

Sort `participants` by `final_roi_bps`, highest first. That order must match each row's `rank`.

If two players have the same ROI, the higher `final_equity` ranks higher. If that is equal too, the smaller maximum drawdown wins, and the report doesn't carry drawdown, so a tie that deep can't be settled from the file alone. The full tie rule is in [Battle rules and scoring](/docs/battles/battle-rules-and-scoring.md#how-ties-break).

In a 5v5 room, players are ranked the same way, but the side with the higher combined PnL wins. The report has no per-player PnL, so you can check each player's rank from the file, but not which side won.

## Recompute the payouts

1. Work out the prize pool: `escrowed_amount − platform_fee − total_referral`. It must equal `total_payout`.
2. Split the pool the way `room.prize_distribution` says:
   * `winner_takes_all`: rank 1 gets the whole pool.
   * `top_3_60_30_10`: rank 1 gets 60% of the pool and rank 2 gets 30%, each rounded down to a whole unit. Rank 3 gets what is left, so the three always add up to the pool exactly.
   * Other formats are described in [Room formats](/docs/battles/room-formats.md).
3. Compare your amounts with `payouts`. Each `recipient_address` must be the `wallet_address` of the player with that `rank`.
4. Check that nothing is missing: `total_payout + total_referral + platform_fee` must equal `escrowed_amount`.

For example, a room with `escrowed_amount` 100000, `platform_fee` 991 and `total_referral` 9 has a pool of 99000. Split 60/30/10, that is 59400, 29700 and 9900.

<details>

<summary>Check a payout against the Merkle root (optional, needs a script)</summary>

Each payout row is one leaf of the tree whose root the escrow stores:

`keccak256(abi.encode(uint256 contract_room_id, uint256 leaf_index, address recipient_address, uint256 amount))`

Hash every leaf in `leaf_index` order, then combine them in pairs, hashing the smaller of each pair first and passing an odd one up unchanged, until one hash is left. That hash must equal `payoutMerkleRoot`. It is the tree OpenZeppelin's `MerkleProof` checks, and the one the escrow checks when you claim.

</details>

## If something doesn't match

[Contact support](/docs/help/troubleshooting.md#when-to-contact-support) with the room you checked and the value that differed. A result is final once the room settles and there is no dispute process, but a mismatch between the report and the chain is something we need to know about. See [Battle rules and scoring](/docs/battles/battle-rules-and-scoring.md#results-are-final).

## Related

* [What is published for each room](/docs/transparency/what-is-published.md)
* [Trade evidence encoding](/docs/transparency/trade-evidence-encoding.md)
* [Your battle statement](/docs/transparency/your-battle-statement.md)
* [Settlement](/docs/funds-and-settlement/settlement.md)
