Risk Level
MEDIUM
Location
core/src/exchanges/smarkets/normalizer.ts:277-284
Code
const balance = parseFloat(raw.balance || '0');
const available = parseFloat(raw.available_balance || '0');
...
return [{
currency: 'GBP',
total: balance,
available,
locked: balance - available, // ← float subtraction
}];
Problem
Two parseFloat calls convert the Smarkets API's balance strings to IEEE 754 floats, then float subtraction derives locked = total - available. Because both balance and available were independently rounded by IEEE 754 at parse time, their difference accumulates two rounding errors. This is structurally identical to the Kalshi normalizeBalance issue (#237).
The locked value is displayed to the user and used for order-sizing decisions.
Example Failure
raw.balance = "99.99"
raw.available_balance = "90.01"
parseFloat("99.99") = 99.99 (exact in this case)
parseFloat("90.01") = 90.01 (exact in this case)
locked = 99.99 - 90.01 = 9.979999999999997 (IEEE 754 — should be 9.98)
// Less round numbers:
raw.balance = "123.33"
raw.available_balance = "111.11"
parseFloat("123.33") = 123.33
parseFloat("111.11") = 111.11
locked = 123.33 - 111.11 = 12.219999999999999 (should be 12.22)
Suggested Fix
Compute locked without independent float rounding:
import Decimal from 'decimal.js';
const balance = new Decimal(raw.balance || '0');
const available = new Decimal(raw.available_balance || '0');
return [{
currency: 'GBP',
total: balance.toNumber(),
available: available.toNumber(),
locked: balance.minus(available).toNumber(),
}];
Found by automated float safety audit
Risk Level
MEDIUM
Location
core/src/exchanges/smarkets/normalizer.ts:277-284Code
Problem
Two
parseFloatcalls convert the Smarkets API's balance strings to IEEE 754 floats, then float subtraction deriveslocked = total - available. Because bothbalanceandavailablewere independently rounded by IEEE 754 at parse time, their difference accumulates two rounding errors. This is structurally identical to the Kalshi normalizeBalance issue (#237).The
lockedvalue is displayed to the user and used for order-sizing decisions.Example Failure
Suggested Fix
Compute
lockedwithout independent float rounding:Found by automated float safety audit