Skip to content

Preserve exact localized payment amounts - #107

Open
Jim8y wants to merge 2 commits into
neoorder:masterfrom
Jim8y:fix/audit-p2-02
Open

Preserve exact localized payment amounts#107
Jim8y wants to merge 2 commits into
neoorder:masterfrom
Jim8y:fix/audit-p2-02

Conversation

@Jim8y

@Jim8y Jim8y commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Problem

Payment amounts were parsed through culture-sensitive decimal values in app links and through inconsistent parsers in the send form. A dot-decimal payment link could change value in a comma-decimal locale, and large/high-precision token amounts could be rounded or rejected prematurely.

Change

  • Preserve payment-link amounts as invariant, ungrouped strings through link parsing and QR navigation.
  • Localize only at the send form's display boundary; validate and convert directly to exact BigInteger token units.
  • Use the same parsing path for submission, bounds checks, and the full-balance action. Fiat estimation remains optional.
  • Reject raw amount strings longer than 1024 characters before whitespace scanning, trimming, splitting, padding, or BigInteger parsing. This also covers payment-link/QR amounts routed through PaymentAction, while preserving valid values at the boundary and exact 60-decimal-place amounts.

This independent PR addresses audit P2-02 only, based on master 623603d.

Validation

  • dotnet test tests/P2-02/TokenAmount.Tests.csproj --no-restore --nologo: 42 regression tests passed, including real PaymentAction/AppLinkAction parsing. The original link-entry regressions failed with the culture-dependent implementation; five follow-up cases failed before the early length guard was added.
  • iOS 26.5 iPhone 17 simulator and Android API 36 arm64 emulator: 90 native-app boolean checks passed on each platform through the actual payment-link model and SendPage/Entry/validation handlers.
  • Covered en-US, de-DE and fr-FR; invariant 1.5 links, amounts beyond decimal precision, exact 60-decimal-place values, minimum units, excessive precision, zero/over-balance input, and the full-balance action. On both platforms, the actual Entry binds a valid 1024-character amount, rejects 1025/16384-character values, and the production PaymentAction/AppLinkAction path rejects overlong amounts.
  • Synthetic balances and a hidden Submit control were used in the external fixture. No live RPC request, transaction signature, or broadcast was performed.
  • After removing the fixture, both platforms passed a full product rebuild (0 warnings, 0 errors) and normal Home/four-tab launch smoke verification. No OneGate app crash was observed. This product smoke check is separate from the native amount assertions.
  • Both follow-up native runs used the staged patch SHA-256 0fa066d30f9fd58875501db9a4ce72ad85a41b98aaf715fce41624678a00c121 relative to the original PR head fbcfd07df28ae55acaeadcb0f6dab3ae07c87bcb.

Screenshots, native result JSON and simulator-only fixture code remain outside the repository.

Limits

The early guard bounds the amount parser's numeric work and intermediate allocations; it does not bound parsing of an entire incoming URI, which occurs before amount validation. Native checks used synthetic balances and direct production controls/models, not a camera scan or an on-chain transfer. No uploaded screenshots, hosted CI success, or combined validation with other audit branches is claimed.

Copilot AI lite review requested due to automatic review settings September 5, 2026 07:08

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new amount parser accepts unbounded-length input from app links/QR, which can lead to excessive allocations/CPU (DoS) unless a reasonable max-length guard is added.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR hardens payment amount handling so protocol-provided amounts are preserved as invariant, ungrouped strings through app-link/QR parsing and only localized at the Send form boundary, avoiding culture-sensitive decimal conversions and precision loss.

Changes:

  • Introduces TokenAmount to format/parse token-unit amounts via BigInteger with culture-aware decimal separators (no grouping, no scientific notation).
  • Updates PaymentAction, ScanPage, and SendPage to carry payment-link amounts as strings until token precision is known, then validate/convert to exact chain units for submission and bounds checks.
  • Adds a dedicated P2-02 regression test project covering locale behavior, precision limits, and real app-link parsing/navigation.
File summaries
File Description
tests/P2-02/TokenAmountTests.cs Adds unit tests for formatting/parsing across locales and precision/bounds edge cases.
tests/P2-02/TokenAmount.Tests.csproj Introduces standalone test project linking production parsing/link code for regression coverage.
tests/P2-02/README.md Documents rationale, scope, and how to run the P2-02 regression suite.
tests/P2-02/PaymentPlatformStubs.cs Provides minimal navigation/platform doubles so linked app-link code can run in tests.
tests/P2-02/PaymentActionTests.cs Verifies payment URIs preserve protocol digits and reject ambiguous/localized inputs.
OneGateApp/Services/TokenAmount.cs Adds exact BigInteger-based formatter/parser with culture-specific decimal separator support.
OneGateApp/Pages/SendPage.xaml.cs Switches amount input to string + exact unit parsing/validation for All/bounds/submission.
OneGateApp/Pages/SendPage.xaml Binds amount entry to AmountText and removes decimal Range validator.
OneGateApp/Pages/ScanPage.xaml.cs Escapes amount when constructing navigation query to preserve exact digits safely.
OneGateApp/Models/AppLinks/PaymentAction.cs Stores amount as invariant string and validates invariant dot-decimal syntax.
OneGateApp.slnx Adds the new P2-02 test project to the solution.
Review details
  • Files reviewed: 11/11 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +20 to +24
units = BigInteger.Zero;
if (string.IsNullOrWhiteSpace(text)) return false;
culture ??= CultureInfo.CurrentCulture;
string[] parts = text.Trim().Split(culture.NumberFormat.NumberDecimalSeparator, StringSplitOptions.None);
if (parts.Length > 2) return false;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants