Security: swap math missing edge-reserve and u128 boundary tests [SEC-C01] #401

Closed
opened 2026-06-19 10:56:59 +00:00 by totdking · 6 comments
totdking commented 2026-06-19 10:56:59 +00:00 (Migrated from gitlab.com)
No description provided.
totdking commented 2026-06-19 10:58:42 +00:00 (Migrated from gitlab.com)

Checklist Item

SEC-C01: Verify constant-product swap accounting cannot return more value than reserves permit after fee/spread. Verify: unit/property tests for swap math, including edge reserves and tiny amounts.


Summary

Tiny-amount and large-amount swap tests exist and pass. However, no test exercises the constant-product formula with reserves near the u128 maximum or with extreme reserve imbalance ratios. An overflow or rounding failure at boundary values could cause the pool to return more than reserves permit.


What Was Checked

  • smartcontracts/tests/src/lib.rs line 12177: test_swap_one_microunit -- tiny amount covered
  • smartcontracts/tests/src/lib.rs line 3934: test_swap_large_amount -- large amount covered
  • smartcontracts/tests/src/lib.rs line 12338: test_no_zero_output_from_rounding -- rounding guard present
  • Searched for u128::MAX, u128 boundary, reserve overflow: no results in test files

Expected (per checklist)

Tests must cover edge reserves including: reserves at or near u128 maximum, extreme reserve imbalance (e.g. 1:1_000_000), and tiny amounts. All cases must confirm that output does not exceed what reserves permit after fee and spread.


Actual

Tiny-amount and sequential-swap tests exist. No test constructs reserves near u128 limits or exercises extremely unbalanced reserve states that stress the constant-product arithmetic boundary.


Evidence

  • smartcontracts/tests/src/lib.rs lines 3934, 12177, 12338: existing coverage for large, tiny, and rounding cases
  • No grep match for u128::MAX or boundary reserve setup in any test file under smartcontracts/tests/src/

Suggested Fix

Add property tests or explicit unit tests in lib.rs or a dedicated math test module covering:

  • Reserves at u128::MAX / 2 and u128::MAX - 1 with a small input
  • Reserve ratio of 1:1_000_000 in both directions
  • Confirm in all cases that output token amount does not exceed reserve balance and that fee split is exact

Verification Checklist

  • Test with reserves near u128 maximum confirms no arithmetic overflow
  • Test with 1:1_000_000 reserve ratio in offer and ask directions confirms output is within bounds
  • All new tests pass in CI
  • No zero-output or negative-output case is reachable under any reserve configuration

Labels

security, pre-launch

Cc: @PlasticDigits

### Checklist Item SEC-C01: Verify constant-product swap accounting cannot return more value than reserves permit after fee/spread. Verify: unit/property tests for swap math, including edge reserves and tiny amounts. --- ### Summary Tiny-amount and large-amount swap tests exist and pass. However, no test exercises the constant-product formula with reserves near the u128 maximum or with extreme reserve imbalance ratios. An overflow or rounding failure at boundary values could cause the pool to return more than reserves permit. --- ### What Was Checked - `smartcontracts/tests/src/lib.rs` line 12177: `test_swap_one_microunit` -- tiny amount covered - `smartcontracts/tests/src/lib.rs` line 3934: `test_swap_large_amount` -- large amount covered - `smartcontracts/tests/src/lib.rs` line 12338: `test_no_zero_output_from_rounding` -- rounding guard present - Searched for u128::MAX, u128 boundary, reserve overflow: no results in test files --- ### Expected (per checklist) Tests must cover edge reserves including: reserves at or near u128 maximum, extreme reserve imbalance (e.g. 1:1_000_000), and tiny amounts. All cases must confirm that output does not exceed what reserves permit after fee and spread. --- ### Actual Tiny-amount and sequential-swap tests exist. No test constructs reserves near u128 limits or exercises extremely unbalanced reserve states that stress the constant-product arithmetic boundary. --- ### Evidence - `smartcontracts/tests/src/lib.rs` lines 3934, 12177, 12338: existing coverage for large, tiny, and rounding cases - No grep match for u128::MAX or boundary reserve setup in any test file under `smartcontracts/tests/src/` --- ### Suggested Fix Add property tests or explicit unit tests in `lib.rs` or a dedicated math test module covering: - Reserves at u128::MAX / 2 and u128::MAX - 1 with a small input - Reserve ratio of 1:1_000_000 in both directions - Confirm in all cases that output token amount does not exceed reserve balance and that fee split is exact --- ### Verification Checklist - [ ] Test with reserves near u128 maximum confirms no arithmetic overflow - [ ] Test with 1:1_000_000 reserve ratio in offer and ask directions confirms output is within bounds - [ ] All new tests pass in CI - [ ] No zero-output or negative-output case is reachable under any reserve configuration --- ### Labels `security`, `pre-launch` Cc: @PlasticDigits
totdking commented 2026-06-19 11:16:16 +00:00 (Migrated from gitlab.com)

mentioned in issue #381

mentioned in issue #381
PlasticDigits commented 2026-06-25 11:42:46 +00:00 (Migrated from gitlab.com)

mentioned in commit 72aedf3024

mentioned in commit 72aedf30245be56ae4e7ba41c8822735c98ee0cc
PlasticDigits commented 2026-06-25 11:42:57 +00:00 (Migrated from gitlab.com)

mentioned in merge request !936

mentioned in merge request !936
PlasticDigits commented 2026-06-25 12:29:19 +00:00 (Migrated from gitlab.com)

mentioned in commit 7227ecd0e5

mentioned in commit 7227ecd0e5089219486c329018121096753dfb33
PlasticDigits commented 2026-06-25 12:32:56 +00:00 (Migrated from gitlab.com)

Verification — #401 / SEC-C01 (PASS)

Verified on main @ 7227ecd0 (merge of issue-401-sec-c01-swap-boundary-tests, commit 72aedf30).

Acceptance checklist

Item Result How verified
Reserves near u128 maximum — no arithmetic overflow PASS sec_c01_swap_boundary_tests::test_swap_reserves_near_u128_max_no_overflow exercises u128::MAX/2 and u128::MAX-1 reserves with 1-unit input; asserts gross output ≤ ask reserve, exact fee split, and on-chain balance conservation.
1:1_000_000 reserve ratio — offer and ask directions, output within bounds PASS test_swap_extreme_imbalance_one_to_one_million_offer_scarce_side (1M:1T, swap scarce A) and test_swap_extreme_imbalance_one_to_one_million_offer_abundant_side (swap abundant B) both assert assert_pool_swap_accounting and actual_return ≤ output_reserve.
All new tests pass in CI PASS cargo test sec_c01_swap_boundary_tests → 3/3 ok; make test-contracts → full suite green.
No zero/negative output reachable under boundary reserves PASS u128-max cases assert gross ≤ output_reserve and zero-gross implies zero return+fee; existing dust_amount_tests::test_no_zero_output_from_rounding and test_swap_one_microunit still pass.

Additional regression checks (issue body references)

Test Result
test_swap_one_microunit PASS
test_swap_large_amount PASS
test_no_zero_output_from_rounding PASS

Implementation location

smartcontracts/tests/src/lib.rs — module sec_c01_swap_boundary_tests (lines ~12676–12948), helper assert_pool_swap_accounting enforces gross ≤ reserve and floor fee split.

No repo changes required during verification; fix already merged.

## Verification — #401 / SEC-C01 (PASS) Verified on `main` @ `7227ecd0` (merge of `issue-401-sec-c01-swap-boundary-tests`, commit `72aedf30`). ### Acceptance checklist | Item | Result | How verified | |------|--------|--------------| | Reserves near u128 maximum — no arithmetic overflow | **PASS** | `sec_c01_swap_boundary_tests::test_swap_reserves_near_u128_max_no_overflow` exercises `u128::MAX/2` and `u128::MAX-1` reserves with 1-unit input; asserts gross output ≤ ask reserve, exact fee split, and on-chain balance conservation. | | 1:1_000_000 reserve ratio — offer and ask directions, output within bounds | **PASS** | `test_swap_extreme_imbalance_one_to_one_million_offer_scarce_side` (1M:1T, swap scarce A) and `test_swap_extreme_imbalance_one_to_one_million_offer_abundant_side` (swap abundant B) both assert `assert_pool_swap_accounting` and `actual_return ≤ output_reserve`. | | All new tests pass in CI | **PASS** | `cargo test sec_c01_swap_boundary_tests` → 3/3 ok; `make test-contracts` → full suite green. | | No zero/negative output reachable under boundary reserves | **PASS** | u128-max cases assert `gross ≤ output_reserve` and zero-gross implies zero return+fee; existing `dust_amount_tests::test_no_zero_output_from_rounding` and `test_swap_one_microunit` still pass. | ### Additional regression checks (issue body references) | Test | Result | |------|--------| | `test_swap_one_microunit` | **PASS** | | `test_swap_large_amount` | **PASS** | | `test_no_zero_output_from_rounding` | **PASS** | ### Implementation location `smartcontracts/tests/src/lib.rs` — module `sec_c01_swap_boundary_tests` (lines ~12676–12948), helper `assert_pool_swap_accounting` enforces gross ≤ reserve and floor fee split. No repo changes required during verification; fix already merged.
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-06-25 12:32:57 +00:00
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/cl8y-dex-terraclassic#401
No description provided.