> 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/trade-evidence-encoding.md).

# Trade evidence encoding

How each fill and close mark becomes one line, how lines are hashed into leaves, and how leaves are combined into the trade\_log\_hash and price\_data\_hash roots.

A v7 or v8 settlement report signs two roots over the room's trades: `hashes.trade_log_hash` over its fills, and `hashes.price_data_hash` over its close marks. This page is the complete rule for rebuilding both from the rows. The [open verifier](/docs/transparency/check-a-result.md#check-it-in-your-browser) applies it in your browser, and you can apply it with any keccak-256 library.

A v8 report publishes the rows in its trade evidence file. A v7 report carries them inside the report itself. The encoding is the same for both, so a room's roots are the same under either version. Encoding version `1` is named in the report as `versions.trade_log_encoding` and in the file as `trade_log_encoding`.

## From a row to a line

Each row becomes one line of text: a tag, then the row's fields in a fixed order, joined by `|` with no spaces.

| Tree                            | Line                                                                                                                           |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| Fills (`trade_log_hash`)        | `ct-fill-v1` \| `executed_at` \| `wallet_address` \| `symbol` \| `side` \| `price` \| `quantity` \| `execution_snapshot_id`    |
| Close marks (`price_data_hash`) | `ct-mark-v1` \| `closed_at` \| `wallet_address` \| `symbol` \| `position_side` \| `quantity` \| `mark_price` \| `close_reason` |

The trade evidence file lists each row's fields in this same order, already in the spelling below, so a line is the row's values joined behind its tag.

Every field has exactly one spelling. A value in any other spelling isn't converted; it means the file isn't the one the report signed.

| Field                   | Spelling                                                                                                                                                                                                                   |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Times                   | UTC, with exactly six fractional digits and a `Z`: `2026-10-30T14:00:00.123456Z`                                                                                                                                           |
| Wallets                 | `0x` and forty lowercase hex digits                                                                                                                                                                                        |
| Prices and quantities   | A positive plain decimal: digits with at most one dot, no sign and no exponent. No leading zeros (a value below one starts `0.`) and no trailing fractional zeros: `171.50` is spelled `171.5`, and `12.0` is spelled `12` |
| `symbol`                | Uppercase letters and digits, such as `SOLUSDT`                                                                                                                                                                            |
| `side`                  | `buy` or `sell`                                                                                                                                                                                                            |
| `position_side`         | `long` or `short`                                                                                                                                                                                                          |
| `close_reason`          | `room_ended`, `liquidation` or `account_liquidation`. A position you closed yourself is a fill, not a close mark                                                                                                           |
| `execution_snapshot_id` | Lowercase                                                                                                                                                                                                                  |

## From a line to a leaf

A leaf is the keccak-256 hash of one byte `0x00` followed by the line's UTF-8 bytes:

`leaf = keccak256(0x00 ‖ line)`

For example, a buy of 12 SOLUSDT at 171.5 is this line, with the wallet written in full where `0x1db3…6ee6` stands:

`ct-fill-v1|2026-10-30T14:00:00.123456Z|0x1db3…6ee6|SOLUSDT|buy|171.5|12|8e1a0b52-6f3c-4d2e-9b1a-0c2d3e4f5a64`

Hash the byte `0x00` and that line's 139 bytes together, not the line alone.

## From leaves to a root

1. Sort the lines by their bytes, ascending. The time comes first and has a fixed width, so this is time order, with ties broken by the remaining fields. The order rows arrive in never changes a root.
2. Hash each line into its leaf, in that order.
3. Combine the leaves in pairs, left to right: `node = keccak256(0x01 ‖ left ‖ right)`. If a level has an odd number of hashes, the last one moves up to the next level unchanged.
4. Repeat until one hash is left. That is the root.

A tree with no rows has the root `0x` followed by sixty-four zeros. A room where the platform closed no position has that `price_data_hash`.

The `0x00` and `0x01` prefixes keep a leaf from ever being read as a node. Unlike the payout tree, pairs aren't sorted before hashing: the left hash is always the earlier one.

## What a match shows

If the roots you rebuild equal the report's, and the report's hash equals the one the escrow stores, then these rows are exactly the ones CounterTrade signed when it settled the room. A match shows which trades the platform recorded. It doesn't independently prove that an execution price matched the market.

## Related

* [Check a result](/docs/transparency/check-a-result.md)
* [Download the report and trade evidence](/docs/transparency/download-the-evidence.md)
* [What is published for each room](/docs/transparency/what-is-published.md)
