# Reentrancy issue with the withdraw method of USDC. All tokens could be drained.

USDA._withdraw transfers sUSD before burning USDA, letting a malicious contract reenter withdraw and drain all USDC reserves.

- Payout: Contest reward
- Severity: high
- Program: Amphora Protocol
- Credited: SanketKogekar
- Disclosed: 2024-04-22
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-07-amphora-findings/issues/304
- Library page: https://bugbountylibrary.com/r/c4%3A2023-07-amphora%3AH-01
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:reentrancy

**Target:** USDA stablecoin contract withdraw/withdrawTo
**Root cause:** _withdraw() violates CEI: it calls sUSD.transfer(_target, _susdAmount) before _burn(_msgSender(), _susdAmount), so the caller's balance is still intact during the external transfer.
**Steps:**
1. Deploy attacker contract holding X USDA.
2. Call USDA.withdraw(X); _withdraw checks balanceOf(msg.sender) >= X, decrements reserveAmount, transfers X sUSD to attacker.
3. In the attacker's receive/fallback, reenter USDA.withdraw(X) again before the original _burn executes.
4. Repeat reentrancy until reserveAmount/USDC balance is exhausted, then let burns settle.
**How found:** Code review of _withdraw ordering: noticed sUSD.transfer precedes _burn, breaking checks-effects-interactions, and that the balance check uses balanceOf(_msgSender()) which is unchanged during the transfer.
**Exploitation:** Attacker contract reenters withdraw from its token-receive hook each time sUSD is transferred, since _burn has not yet reduced its balance; each iteration passes the balanceOf check and pulls another _susdAmount of sUSD until the protocol reserve is drained.
**Insight:** In stablecoin mint/redeem contracts, check the burn/mint ordering relative to the external token transfer; a balanceOf-based guard is only safe if the burn happens before the transfer, otherwise the receive hook reenters with an unchanged balance.
