# Token approve allowance edge cases

approve/safeApprove/forceApprove calls that assume standard ERC20 allowance and return semantics

_Area: Smart contract access control and control flow. Seen in 5 disclosed reports; latest 2025-05-23. Updated 2026-10-23._

## How it works
Code assumes every ERC20 behaves like a textbook token: `approve` returns a bool, accepts any new allowance value, and `transferFrom(self, ...)` works without an allowance. Real tokens break each assumption. USDT returns no data, so a raw `IERC20.approve` expecting a bool reverts on the return-length check [E2](https://bugbountylibrary.com/r/sherlock%3A2023-07-blueberry%3AM-13.md). USDT-style tokens revert when changing a non-zero allowance to another non-zero value, so a second approval fails [E3](https://bugbountylibrary.com/r/sherlock%3A2022-10-illuminate%3AM-10.md)[E5](https://bugbountylibrary.com/r/c4%3A2022-04-backd%3AH-03.md). Some tokens (BNB) revert on `approve(0)`, so clearing an allowance fails [E4](https://bugbountylibrary.com/r/c4%3A2025-03-silo-finance%3AM-03.md). Arbitrum's WETH lacks WETH9's self-transfer allowance bypass, so `transferFrom(address(this), ...)` reverts [E1](https://bugbountylibrary.com/r/c4%3A2024-07-benddao%3AM-05.md). The broken assumption is that allowance state is freely settable and self-transfers are free.

## Where it shows up
- Raw `IERC20.approve`/`transferFrom` instead of SafeERC20 wrappers, in a protocol claiming USDT/USDC support [E2](https://bugbountylibrary.com/r/sherlock%3A2023-07-blueberry%3AM-13.md)
- `safeApprove` called on repeat user actions without resetting allowance to zero first [E5](https://bugbountylibrary.com/r/c4%3A2022-04-backd%3AH-03.md)
- Factory/market contracts approving an underlying per deployment, sharing one allowance holder across markets [E3](https://bugbountylibrary.com/r/sherlock%3A2022-10-illuminate%3AM-10.md)
- `forceApprove`/`approve(0)` used to clear allowances on tokens that reject zero approvals [E4](https://bugbountylibrary.com/r/c4%3A2025-03-silo-finance%3AM-03.md)
- `transferFrom(address(this), ...)` for the contract's own wrapped-native balance [E1](https://bugbountylibrary.com/r/c4%3A2024-07-benddao%3AM-05.md)

## How to review
For every approve/transferFrom site, identify the concrete token and check the invariant: the call must succeed for that token's actual return data and allowance rules. Confirm bool-returning calls are wrapped (SafeERC20) or the token is known to return bool [E2](https://bugbountylibrary.com/r/sherlock%3A2023-07-blueberry%3AM-13.md). Confirm re-approval paths either reset to zero first, use `safeIncreaseAllowance`, or target a token that permits non-zero-to-non-zero [E3](https://bugbountylibrary.com/r/sherlock%3A2022-10-illuminate%3AM-10.md)[E5](https://bugbountylibrary.com/r/c4%3A2022-04-backd%3AH-03.md). Confirm clearing paths do not rely on `approve(0)` for tokens that reject it [E4](https://bugbountylibrary.com/r/c4%3A2025-03-silo-finance%3AM-03.md). Confirm self-transfers use `transfer`, not `transferFrom(self,...)` [E1](https://bugbountylibrary.com/r/c4%3A2024-07-benddao%3AM-05.md).

## Variants seen
- Non-standard return data (USDT) reverting on ABI length check [E2](https://bugbountylibrary.com/r/sherlock%3A2023-07-blueberry%3AM-13.md)
- Non-zero-to-non-zero approve revert blocking repeat actions [E3](https://bugbountylibrary.com/r/sherlock%3A2022-10-illuminate%3AM-10.md)[E5](https://bugbountylibrary.com/r/c4%3A2022-04-backd%3AH-03.md)
- Zero-value approve revert blocking market removal [E4](https://bugbountylibrary.com/r/c4%3A2025-03-silo-finance%3AM-03.md)
- Missing self-transfer allowance bypass on forked WETH [E1](https://bugbountylibrary.com/r/c4%3A2024-07-benddao%3AM-05.md)

## Why fixes fail
`forceApprove`'s reset-to-zero fallback re-issues the same failing `approve(0)` call on tokens that reject it, so removal still reverts [E4](https://bugbountylibrary.com/r/c4%3A2025-03-silo-finance%3AM-03.md).

## Impact and severity
Medium to high: vaults/markets become unusable [E2](https://bugbountylibrary.com/r/sherlock%3A2023-07-blueberry%3AM-13.md)[E3](https://bugbountylibrary.com/r/sherlock%3A2022-10-illuminate%3AM-10.md), positions left unprotected from liquidation [E5](https://bugbountylibrary.com/r/c4%3A2022-04-backd%3AH-03.md), market removal and queue updates blocked [E4](https://bugbountylibrary.com/r/c4%3A2025-03-silo-finance%3AM-03.md), and core wrap/cross-lending flows broken on Arbitrum [E1](https://bugbountylibrary.com/r/c4%3A2024-07-benddao%3AM-05.md). Severity rises when the failure hits liquidation protection or locks funds permanently.

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2024-07-benddao%3AM-05.md
- E2: https://bugbountylibrary.com/r/sherlock%3A2023-07-blueberry%3AM-13.md
- E3: https://bugbountylibrary.com/r/sherlock%3A2022-10-illuminate%3AM-10.md
- E4: https://bugbountylibrary.com/r/c4%3A2025-03-silo-finance%3AM-03.md
- E5: https://bugbountylibrary.com/r/c4%3A2022-04-backd%3AH-03.md
