# boundedSub() might fail to return the result that is bounded to prevent overflows

boundedSub() in GMX Calc.sol used a wrong underflow check, so subtracting from near-int256.min reverts instead of clamping, breaking fault-tolerant math.

- Payout: Contest reward
- Severity: medium
- Program: Gmx
- Credited: chaduke
- Disclosed: 2022-09-22
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2023-02-gmx-judging/issues/16
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-02-gmx%3AM-38
- Tags: domain:web3 impact:dos kind:contest platform:sherlock sev:medium tech:solidity technique:source-review vuln:accounting-error

**Target:** Solidity math utility Calc.sol boundedSub()
**Root cause:** The underflow guard `a < 0 && b <= type(int256).min - a` is algebraically wrong; it should test `a <= type(int256).min + b`, so cases like a=int256.min, b=1 slip through and `a - b` reverts.
**Steps:**
1. Read boundedSub() in gmx-synthetics/contracts/utils/Calc.sol
2. Note case 3 condition `a < 0 && b <= type(int256).min - a`
3. Pick a = type(int256).min+3, b = 4 (or a=int256.min, b=1)
4. Condition fails, falls through to `return a - b` which underflows and reverts
5. Reproduce in Remix: `boundedSub(type(int256).min+3, 4)` reverts
**How found:** Manual code review of the bounded arithmetic helper; algebraically checked each branch's overflow/underflow guard against boundary inputs and found case 3's inequality mis-derived.
**Insight:** When auditing saturating/clamping math helpers, substitute exact boundary values (type(int256).min, max) into each guard and verify the inequality is algebraically equivalent to the intended `a - b < min` / `a - b > max` test; off-by-sign rewrites of the guard silently defeat the clamp.
