# [WP-H0] Fake balances can be created for not-yet-existing ERC20 tokens, which allows attackers to set traps to steal funds from future users

Cally's use of solmate SafeTransferLib skips code-existence checks, letting attackers create vaults with fake balances for not-yet-deployed tokens and later withdraw real tokens once deployed at the same address.

- Payout: Contest reward
- Severity: high
- Program: Cally
- Credited: WatchPug
- Disclosed: 2022-07-01
- Write-up quality: 8/10
- Original: https://github.com/code-423n4/2022-05-cally-findings/issues/225
- Library page: https://bugbountylibrary.com/r/c4%3A2022-05-cally%3AH-03
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:chained technique:source-review vuln:accounting-error vuln:business-logic

**Target:** Cally.sol createVault ERC20 vault creation
**Root cause:** solmate SafeTransferLib does not verify the token address has code, so safeTransferFrom on a codeless address silently succeeds while the vault is still credited with the amount.
**Steps:**
1. Attacker calls `createVault(10000e18, TokenA_address, ...)` where TokenA has no code on this chain; tx succeeds and vault records 10000e18 balance
2. Repeat for TokenB, TokenC addresses that are codeless locally but exist on other chains
3. Later ProjectB deploys TokenB at the same address on this chain
4. Alice creates a vault depositing `11000e18 TokenB`
5. Attacker calls `initiateWithdraw()` then `withdraw()` on the trapped vault to receive `10000e18 TokenB`
**How found:** Noticed solmate's SafeTransferLib explicitly documents it does not check token code, unlike OZ SafeERC20; connected this to the qBridge hack pattern and cross-chain same-address token deployments.
**Exploitation:** Attacker pre-creates vaults against deterministic cross-chain token addresses with no local code, paying nothing. When the real token is later deployed at that address, the attacker's vault holds a phantom balance backed by other users' deposits, which the attacker withdraws.
**Escalation:** Scaling by setting traps on many potential cross-chain token addresses simultaneously.
**Insight:** When a protocol pulls arbitrary user-specified ERC20 addresses, check whether the transfer lib verifies code existence; codeless addresses plus deterministic cross-chain deployment addresses enable pre-planted vault traps.
