# Customers cannot be topUp()ed a second time

Backd's topUp handlers call safeApprove with non-zero allowance on repeat top-ups, reverting and leaving positions unprotected from liquidation.

- Payout: Audit contest
- Severity: high
- Program: Backd
- Credited: IllIllI
- Disclosed: 2022-06-02
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-04-backd-findings/issues/178
- Library page: https://bugbountylibrary.com/r/c4%3A2022-04-backd%3AH-03
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:business-logic

**Target:** Solidity top-up action handlers (CompoundHandler, AaveHandler, TopUpAction)
**Root cause:** OpenZeppelin safeApprove reverts when setting a non-zero allowance over an existing non-zero allowance; handlers never reset allowance to zero before re-approving.
**Steps:**
1. Call topUp() once for a Compound/Aave position, leaving a non-zero allowance to ctoken/lendingPool/feeHandler.
2. Call topUp() again for the same underlying; safeApprove(address(ctoken), amount) at CompoundHandler.sol#L71 reverts with 'approve from non-zero to non-zero allowance'.
3. Same revert occurs in _repayAnyDebt path, AaveHandler.sol#L53, and TopUpAction._payFees at L847.
**How found:** Code review of top-up handlers noticing repeated safeApprove calls without zeroing allowance, matching OpenZeppelin SafeERC20's documented revert condition.
**Exploitation:** Not an attacker-driven exploit; a user calling topUp a second time reverts, so their position is not topped up and can be liquidated despite believing they are protected.
**Insight:** When auditing contracts that reuse OpenZeppelin safeApprove across repeated user actions, check whether allowance is reset to zero or safeIncreaseAllowance is used; any second invocation with non-zero prior allowance bricks the flow.
