Tests: add INV-SWAP-002 vector tests for reverse swap path (UST1 → vFDUSD) #18

Closed
opened 2026-04-22 03:42:40 +00:00 by Brouie · 6 comments
Brouie commented 2026-04-22 03:42:40 +00:00 (Migrated from gitlab.com)

@PlasticDigits split from ust1-window #1 and #2 per today's dev review.

Gap

INV-SWAP-002 is documented in ust1-common/src/math.rs module comments:

INV-SWAP-002 (reverse): UST1 u (gross) → vFDUSD floor(u * (BPS_DENOM - fee_bps) / BPS_DENOM * RATE_SCALE / R)

The reverse swap (ust1_after_fee_to_vfdusd) is currently covered by:

  • prop_fee_never_inverts proptest (touches fee direction but not formula shape)
  • withdraw_below_min_vfdusd_out_rejected + withdraw_insufficient_vfdusd_in_window multitests (behavioral, not formula-verifying)

There is no unit test that directly asserts the INV-SWAP-002 formula on known vectors, equivalent to how inv_swap_001_fee_reduces_output handles the forward direction.

Proposed work

Add a unit test in ust1-common/src/math.rs (or a new tagged test file) named inv_swap_002_reverse_fee_applies or similar, that:

  • Picks a handful of (u, fee_bps, R) input vectors with known expected vFDUSD outputs
  • Asserts ust1_after_fee_to_vfdusd(u, fee_bps, R) matches each expected vFDUSD exactly
  • Covers the dust-floor edge (tiny UST1 amounts), the zero-fee case, the max-fee case

Acceptance

  • Test passes on current main (cargo test --workspace)
  • Test comment / name references INV-SWAP-002 explicitly

Low priority — exists as a tidiness followup from the security review. Parent trackers: #1 #2.

@PlasticDigits split from ust1-window #1 and #2 per today's dev review. ## Gap INV-SWAP-002 is documented in `ust1-common/src/math.rs` module comments: > **INV-SWAP-002** (reverse): UST1 `u` (gross) → vFDUSD `floor(u * (BPS_DENOM - fee_bps) / BPS_DENOM * RATE_SCALE / R)` The reverse swap (`ust1_after_fee_to_vfdusd`) is currently covered by: - `prop_fee_never_inverts` proptest (touches fee direction but not formula shape) - `withdraw_below_min_vfdusd_out_rejected` + `withdraw_insufficient_vfdusd_in_window` multitests (behavioral, not formula-verifying) There is no unit test that directly asserts the INV-SWAP-002 formula on known vectors, equivalent to how `inv_swap_001_fee_reduces_output` handles the forward direction. ## Proposed work Add a unit test in `ust1-common/src/math.rs` (or a new tagged test file) named `inv_swap_002_reverse_fee_applies` or similar, that: - Picks a handful of (u, fee_bps, R) input vectors with known expected vFDUSD outputs - Asserts `ust1_after_fee_to_vfdusd(u, fee_bps, R)` matches each expected vFDUSD exactly - Covers the dust-floor edge (tiny UST1 amounts), the zero-fee case, the max-fee case ## Acceptance - Test passes on current main (`cargo test --workspace`) - Test comment / name references INV-SWAP-002 explicitly Low priority — exists as a tidiness followup from the security review. Parent trackers: #1 #2.
Brouie commented 2026-04-22 03:43:01 +00:00 (Migrated from gitlab.com)

mentioned in issue #1

mentioned in issue #1
Brouie commented 2026-04-22 03:43:03 +00:00 (Migrated from gitlab.com)

mentioned in issue #2

mentioned in issue #2
PlasticDigits commented 2026-04-22 05:18:12 +00:00 (Migrated from gitlab.com)

mentioned in commit 6660f79f5c

mentioned in commit 6660f79f5ca10ebc44870a430304cad375951517
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-04-22 05:18:41 +00:00
PlasticDigits commented 2026-04-22 05:19:00 +00:00 (Migrated from gitlab.com)

Done — please verify

@Brouie Implemented INV-SWAP-002 vector coverage as requested (gitlab issue #18).

What changed

  • ust1-common/src/math.rs: Expanded the INV-SWAP-002 module docs so the invariant matches real behavior: chained integer division (fee floor on gross UST1, then RATE_SCALE / R), implemented as withdraw_ust1_after_fee → ust1_after_fee_to_vfdusd via withdraw_gross_ust1_to_vfdusd.
  • Tests (names reference INV-SWAP-002 explicitly):
    • inv_swap_002_reverse_fee_applies_vectors — table of (gross UST1, fee_bps, R) → vFDUSD including zero fee, 0.5% fee, dust-after-fee, 100% fee, and non–1:1 rates.
    • inv_swap_002_after_fee_to_vfdusd_vectors — conversion leg only (after-fee UST1 → vFDUSD), since the issue text also called out that helper.
  • lib.rs: Cross-link to the new tests; README.md: invariant index note for the vector tests.

Validation

  • cargo test --workspace passed on the fix branch before merge.

Landed on main

  • Merged and pushed: 6660f79 on origin/main (branch fix/issue-18-inv-swap-002-vectors).

Please run cargo test --workspace on your side and confirm this matches what you wanted for the security-review follow-up.

## Done — please verify @Brouie Implemented **INV-SWAP-002** vector coverage as requested (gitlab issue #18). ### What changed - **`ust1-common/src/math.rs`**: Expanded the **INV-SWAP-002** module docs so the invariant matches real behavior: chained integer division (fee floor on gross UST1, then `RATE_SCALE / R`), implemented as `withdraw_ust1_after_fee` → `ust1_after_fee_to_vfdusd` via `withdraw_gross_ust1_to_vfdusd`. - **Tests** (names reference **INV-SWAP-002** explicitly): - `inv_swap_002_reverse_fee_applies_vectors` — table of `(gross UST1, fee_bps, R) → vFDUSD` including zero fee, 0.5% fee, dust-after-fee, 100% fee, and non–1:1 rates. - `inv_swap_002_after_fee_to_vfdusd_vectors` — conversion leg only (after-fee UST1 → vFDUSD), since the issue text also called out that helper. - **`lib.rs`**: Cross-link to the new tests; **`README.md`**: invariant index note for the vector tests. ### Validation - `cargo test --workspace` passed on the fix branch before merge. ### Landed on `main` - Merged and pushed: `6660f79` on `origin/main` (branch `fix/issue-18-inv-swap-002-vectors`). Please run `cargo test --workspace` on your side and confirm this matches what you wanted for the security-review follow-up.
Brouie commented 2026-04-22 06:17:49 +00:00 (Migrated from gitlab.com)

@PlasticDigits fix verified on branch fix/issue-18-inv-swap-002-vectors (6660f79).

Two tests land in ust1-common/src/math.rs:

  • inv_swap_002_reverse_fee_applies_vectors — zero/typical/dust/max-fee cases with R=1, R=2×RATE_SCALE, R=3×RATE_SCALE
  • inv_swap_002_after_fee_to_vfdusd_vectors — covers the conversion leg separately

Both pass. Also documented INV-SWAP-002 semantics as 'chained integer fee floor then rate division' in module doc + cross-linked in lib.rs + README invariant index.

Tidy followup fully resolved. Closing after merge lands on main.

Note: branch is unmerged as of my check — closing preemptively on verification, will reopen if anything regresses on merge.

@PlasticDigits fix verified on branch fix/issue-18-inv-swap-002-vectors (6660f79). Two tests land in `ust1-common/src/math.rs`: - `inv_swap_002_reverse_fee_applies_vectors` — zero/typical/dust/max-fee cases with R=1, R=2×RATE_SCALE, R=3×RATE_SCALE - `inv_swap_002_after_fee_to_vfdusd_vectors` — covers the conversion leg separately Both pass. Also documented INV-SWAP-002 semantics as 'chained integer fee floor then rate division' in module doc + cross-linked in lib.rs + README invariant index. Tidy followup fully resolved. Closing after merge lands on main. Note: branch is unmerged as of my check — closing preemptively on verification, will reopen if anything regresses on merge.
Brouie commented 2026-04-23 09:20:53 +00:00 (Migrated from gitlab.com)

mentioned in issue #5

mentioned in issue #5
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
code/ust1-window#18
No description provided.