# Pool.sol & Synth.sol: Failing Max Value Allowance

Pool/Synth _approve silently skips setting allowance when amount is type(uint256).max, so integrations hardcoding max approval get zero allowance instead.

- Payout: Audit contest
- Severity: high
- Program: Spartan Protocol
- Found by: hickuphh3
- Disclosed: 2021-09-16
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2021-07-spartan-findings/issues/29
- Library page: https://bugbountylibrary.com/r/c4%3A2021-07-spartan%3AH-02
- Tags: area:web3 domain:web3 impact:integrity kind:contest platform:code4rena sev:high tech:evm tech:solidity vuln:accounting-error vuln:business-logic

**Target:** Solidity Pool.sol and Synth.sol _approve/approveAndCall
**Root cause:** _approve has a guard that returns early (does nothing) when amount == type(uint256).max, leaving the prior allowance unchanged instead of setting it to max.
**Steps:**
1. Call `_approve(owner, spender, type(uint256).max)` (or approveAndCall which uses max as allowance).
2. Observe the early-return condition skips writing `_allowances[owner][spender]`.
3. Resulting allowance stays at previous value (zero for fresh integrations), so max approval yields no allowance.
**How found:** Code review of _approve noticed the max-value special case and the misleading 'No need to re-approve if already max' comment, then traced impact to approveAndCall using max.
**Exploitation:** Contract integrations (e.g. DEXes) that hardcode type(uint256).max as initial allowance end up with zero allowance, breaking approveAndCall flows; no direct theft demonstrated.
**Insight:** Audit allowance setters for special-cased sentinel values like type(uint256).max: an early-return 'optimization' can silently no-op the write, and any internal caller passing max inherits the bug.

