Risk Level
HIGH
Location
core/src/exchanges/opinion/normalizer.ts:195-198
Code
normalizePosition(raw: OpinionRawPosition): Position {
const sharesOwned = parseNumStr(raw.sharesOwned);
const currentValue = parseNumStr(raw.currentValueInQuoteToken);
const currentPrice = sharesOwned > 0 ? currentValue / sharesOwned : 0;
return {
...
entryPrice: parseNumStr(raw.avgEntryPrice),
currentPrice,
unrealizedPnL: parseNumStr(raw.unrealizedPnl),
};
}
(parseNumStr wraps parseFloat)
Problem
currentPrice is derived by dividing two parseFloat values. Division of two IEEE 754 floats produces a result that can differ from the true rational quotient by up to 1 ULP. Since prediction market prices must live in [0, 1], errors around common rational values like 1/3, 2/3, 0.1, 0.4 can produce prices that differ by more than the market's minimum tick (0.001).
Example Failure
raw.currentValueInQuoteToken = "66.67" // USDC value of position
raw.sharesOwned = "100" // 100 shares
parseNumStr("66.67") = 66.67000000000000284
parseNumStr("100") = 100
currentPrice = 66.67000000000000284 / 100 = 0.6667000000000000284
// Correct: 0.6667
// Returned: 0.6667000000000000284
// Displayed or compared: may show as 0.6667000000000000 (OK) or 0.6667000000000001 (wrong tick)
For smaller share sizes (e.g. 3 shares), division produces irrational decimals that diverge from any valid market tick.
Suggested Fix
Use Decimal.js for the division, or round to the market's tick size after computing:
const currentPrice = sharesOwned > 0
? new Decimal(currentValue).dividedBy(sharesOwned).toNumber()
: 0;
Found by automated float safety audit
Risk Level
HIGH
Location
core/src/exchanges/opinion/normalizer.ts:195-198Code
(
parseNumStrwrapsparseFloat)Problem
currentPriceis derived by dividing twoparseFloatvalues. Division of two IEEE 754 floats produces a result that can differ from the true rational quotient by up to 1 ULP. Since prediction market prices must live in [0, 1], errors around common rational values like 1/3, 2/3, 0.1, 0.4 can produce prices that differ by more than the market's minimum tick (0.001).Example Failure
For smaller share sizes (e.g. 3 shares), division produces irrational decimals that diverge from any valid market tick.
Suggested Fix
Use
Decimal.jsfor the division, or round to the market's tick size after computing:Found by automated float safety audit