Skip to content

Eliminate floating-point drift in aggregated financial figures #17

Description

@chonilius

Problem

Bounty.reward, Milestone.budget/distributed, and MaintenancePool.monthlyDeposit/balance are all JS numbers by the time they reach components, converted via bare Number(raw.field) in src/lib/adapters.ts from backend decimal strings. src/lib/utils.ts presumably has currency formatting per the README. Every arithmetic operation performed on these numbers in the UI — sums for a maintainer's dashboard "total open bounty value," percentage-remaining bars on milestones (distributed / budget), sponsor "budget remaining" calculations — happens in IEEE-754 floating point. For USDC amounts (which realistically carry up to 7 decimal places on Stellar) and XLM (7 decimal places natively), floating-point arithmetic on sums across many bounties can produce values that don't exactly match the sum a user would compute by hand or that the Soroban contract computes on-chain in fixed-point i128, leading to displayed totals that are off by fractions of a cent — individually trivial, but a plausible source of "why don't your numbers add up" support tickets and, more seriously, of subtly wrong displayed "budget remaining" figures that could mislead a sponsor's funding decision.

Why this is hard

  • Requires finding every place in the codebase that sums, subtracts, or takes percentages of these financial fields — dashboard aggregate stat cards (StatCard.tsx usage sites), milestone progress bars, sponsor budget-remaining calculations — since this is a cross-cutting numeric-correctness issue, not a single function.
  • Converting to a fixed-point/decimal-safe representation (e.g. represent amounts as integer minor units, or adopt a decimal arithmetic approach) touches the adapter layer, the type definitions (Bounty.reward: number etc. in src/types/index.ts would need to change or be supplemented), and every display/formatting call site — this is a type-level refactor with real blast radius, not a local patch.
  • Must decide the right boundary: does precision matter enough to justify a bignum/decimal library dependency (weigh against the "no such dependency currently exists" baseline and bundle size), or is rounding to a defined display precision at the point of aggregation (summing minor units as integers, only converting to display-scale float at the very last formatting step) sufficient and lower-risk?
  • Needs realistic test fixtures that actually expose float drift (e.g. summing many small USDC amounts with repeating decimals) to prove the fix does something, since naive test cases with round numbers won't reveal the bug.

Scope

  • Identify every aggregate/derived-arithmetic call site operating on money fields.
  • Introduce an integer-minor-units (or equivalent decimal-safe) internal representation for aggregation, converting to display-precision only at final formatting via src/lib/utils.ts.
  • Update adapters.ts and relevant types as needed to carry minor-unit or decimal-safe values through to aggregation points.
  • Add regression tests with fixtures specifically chosen to expose float-summation drift, proving they fail before the fix and pass after.

Acceptance criteria

  • A constructed test summing N USDC amounts with repeating-decimal values matches the exact expected sum (no float drift) in all aggregate displays (dashboard stat cards, milestone progress, sponsor budget-remaining).

Metadata

Metadata

Assignees

No one assigned

    Labels

    GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26architectureArchitecture/design issuebugSomething isn't workingvery hardVery difficult task, expert-level effort required

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions