FX fees and rounding
FX fees and rounding
OpenPoly uses integer units. The execution FX rules below apply to Opinion quotes, trades, sells, and redemptions. Polyflight wallet amounts follow the separate native-money boundary at the end of this page.
Units
- credits-equivalent: integer,
10000 = 1 USDT - shares: integer micro-shares,
1000000 = 1 share - IDR: integer minor unit, exponent
0 - FX rate: IDR per
1 USDT - BPS denominator:
10000
No floating settlement values are persisted.
FX freshness
- target freshness:
<= 30seconds - hard stale threshold:
120seconds - stale FX beyond hard threshold -> execution fails before wallet mutation
Fee model
Current wallet quote conversion applies:
fx_fee_bps
operator_fee_bps is still stored on the operator and appears in trade reporting as the operator's share of AMM trade fees, but the current Mini App quote/execution path does not add it to wallet buy/sell/redemption conversion formulas.
Rules:
- fee values are non-negative integers
fx_fee_bps + operator_fee_bpsmust stay< 10000at operator-config validation time- buy applies fee before AMM quote
- sell and redemption apply fee after credits-equivalent proceeds known
Buy formula
Given:
amount_minoridr_per_usdtfx_fee_bps
net_bps = 10000 - fx_fee_bps
credits_equivalent = floor(amount_minor * net_bps * 10000 / (10000 * idr_per_usdt))
Debit amount remains original amount_minor.
Sell formula
Given AMM credits-equivalent proceeds:
net_bps = 10000 - fx_fee_bps
external_amount_minor = floor(credits * idr_per_usdt * net_bps / (10000 * 10000))
Redemption formula
credits_equivalent = floor(shares_micro * 10000 / 1000000)
net_bps = 10000 - fx_fee_bps
external_amount_minor = floor(credits_equivalent * idr_per_usdt * net_bps / (10000 * 10000))
Rounding rule
Always floor final integer conversion. Never round up payout or buying power.
Quote safety
Execution rejects when:
- quote ID missing or changed
- FX snapshot stale beyond hard threshold
- final execution worse than accepted slippage
Why this matters for operators
- wallet side always sees integer IDR minor amounts
- webhook and reporting APIs expose already-rounded final values
- operator reconciliation should compare integer amounts only
Polyflight boundary
Polyflight debits the exact IDR stake and credits the exact stored IDR win, full refund, or compensation. It does not use fx_fee_bps, operator_fee_bps, Opinion quote snapshots, slippage, or current FX at any wallet boundary.
Before boarding, a v5 flight freezes one canonical 8-decimal Indodax USDT_IDR observation only to compare aggregate native IDR and Credits option activity. A refresh failure may use the latest persisted valid observation and disclose fallbackUsed plus age. The committed observation is not refreshed for purchase, lock, result, payout, or replay. No valid observation means IDR is unavailable for that flight while Credits participation continues.
