# codehash check in factory contracts does not account for non-empty addresses

Wildcat factory contracts used codehash != 0 to detect deployed contracts, but a 1 wei transfer makes an empty address return keccak256(""), bypassing the check and bricking deployments or skipping escrow creation.

- Payout: Contest reward
- Severity: high
- Program: Wildcat Protocol
- Credited: MiloTruck
- Disclosed: 2023-12-11
- Write-up quality: 8/10
- Original: https://github.com/code-423n4/2023-10-wildcat-findings/issues/491
- Library page: https://bugbountylibrary.com/r/c4%3A2023-10-wildcat%3AH-02
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:business-logic vuln:dos vuln:misconfiguration

**Target:** Solidity factory contracts (WildcatMarketControllerFactory, WildcatMarketController, WildcatSanctionsSentinel)
**Root cause:** Using `<address>.codehash != bytes32(0)` to detect existing code is wrong per EIP-1052/161: a non-empty account (e.g. 1 wei balance) with no code returns keccak256("") instead of 0, so the check falsely reports code exists.
**Steps:**
1. Call `computeControllerAddress(borrower)` to get the CREATE2 controller address.
2. Transfer 1 wei to that address so its codehash becomes keccak256("").
3. Borrower calls `deployController()`; the `controller.codehash != bytes32(0)` check passes and reverts with ControllerAlreadyDeployed, permanently (salt is fixed to borrower).
4. Same for `computeMarketAddress(...)` + 1 wei + `deployMarket()` reverting with MarketAlreadyDeployed.
5. For escrow: compute `getEscrowAddress(borrower, lender, asset)`, send 1 wei, then `nukeFromOrbit()`/`executeWithdrawal()` returns the undeployed escrow address and transfers lender tokens there, unrecoverable.
**How found:** Code review of factory deployment guards; recognized that EIP-1052 codehash semantics differ for empty vs non-empty code-less accounts per EIP-161, then reasoned that a 1 wei transfer flips the check.
**Exploitation:** Attacker only needs 1 wei and gas: front-run by computing the deterministic CREATE2 address, sending 1 wei to make codehash non-zero, then the victim's deploy call reverts (DoS) or the escrow path silently returns an address with no code, trapping sanctioned lender funds.
**Escalation:** Permanent lockout of a borrower from all protocol functionality (controller salt fixed); escrow variant causes actual loss of sanctioned lender funds.
**Insight:** Never use `.codehash != 0` as an existence check on EVM addresses; use `.code.length != 0`. Any CREATE2 address guard is griefable by dusting the predicted address, so treat deterministic deployment guards as attacker-influenceable.
