chordDocs

Trading

Prices and rounding

How the minimum is computed from your limit, and how output rounds.

Every number on chain is an integer in token base units. The app shows human prices; the program works in raw ones. This page shows how one becomes the other, and how each rounding step is chosen so a fill at exactly your limit still goes through.

#Price units

A market has a base token A and a quote token B. Chord’s price is a fraction of two u64 integers: raw B per raw A. The price you see is that fraction scaled by the decimals of both tokens:

Text
human price = (numerator / denominator) × 10^(decimals A − decimals B)

For a pair with 9-decimal A and 6-decimal B, a committed price of 14220 / 100000 raw B per raw A reads as 142.20 B per A.

#Your minimum

When you sign, the app turns your amount and limit into You receive at least, the minBuyAmount in your order. With the limit written as a fraction n / d in human units:

YouMinimum, in raw units of what you buy
Sell A for Bfloor(sell × n × 10^decB / (d × 10^decA))
Sell B for Afloor(sell × d × 10^decA / (n × 10^decB))

Rounding down makes your minimum a hair more lenient than the exact limit, never stricter, so a batch that clears exactly at your limit fills you.

#Example: selling

Sell 2 A (2000000000 raw, 9 decimals) with a limit of 142.20 B per A (6 decimals):

Text
floor(2000000000 × 14220 × 10^6 / (100 × 10^9)) = 284400000 raw B = 284.40 B

#Example: buying

Pay 500 B (500000000 raw) with a limit of 143.00 B per A:

Text
floor(500000000 × 100 × 10^9 / (14300 × 10^6)) = 3496503496 raw A ≈ 3.4965 A

#Your output

At a committed price p = numerator / denominator, the program pays:

You sellOutput
Afloor(sell × numerator / denominator) raw B
Bfloor(sell × denominator / numerator) raw A

The program then checks everything you’ve received against your minimum, scaled to everything sold so far: received ≥ ceil(sold × minBuy / sell). A fill that fails this check is rejected outright; it can’t pay you a little less.

#Partial fills

If you allow partial fills, a fill can cover part of your sell amount. The program tracks your cumulative sold and received amounts on the order’s receipt and pays each increment as the difference between floor(cumulative sell × price) and what it already paid you. Splitting a fill can’t create or lose a base unit: three partial fills pay exactly what one fill of the same total would.

Very small partial fills can fail the proportional minimum because of rounding. Solvers avoid them.

#The same price for everyone

Every fill in a batch uses the one price in the batch account. Two orders on the same side with the same amount receive exactly the same output, whatever their limits and whenever they were signed. Your limit decides whether you fill, not what you get.