Full Report
In the Wildcat protocol, the WildcatMarketControllerFactory is used for deploying a contracts. The function determines if the contract has been deployed to by checking if the codehash is bytes32(0). At first glance, this seems reasonable but has a weird flaw. Addresses only return 0x0 as the codehash if they are empty. What does empty mean here? The 0x0 is only returned when is it COMPLETELY empty. If it is an account without account (aka funds exist there), then the empty hash is returned. If anyone transfers 1 wei to that address, then the protocol is harmed. The deployments of many things will simply NOT work. MiloTruck seemed very proud of this finding, and I agree, it's pretty sick! I didn't know the difference between an empty account and a non-existent account for a codehash.
Analysis Summary
# Vulnerability: Incorrect Codehash Validation for Non-Empty Addresses
## CVE Details
- **CVE ID**: N/A (Smart Contract Protocol Finding)
- **CVSS Score**: 7.5 (High) - Estimated based on protocol-wide DoS potential.
- **CWE**: CWE-691: Insufficient Control Flow Integrity / Invalid Validation.
## Affected Systems
- **Products**: Wildcat Protocol
- **Versions**: 2023-10 Audit Scope (Commit `main`)
- **Configurations**: Factory contracts using `EXTCODEHASH` to determine deployment state, specifically:
- `WildcatMarketControllerFactory.sol`
- `WildcatMarketController.sol`
- `WildcatSanctionsSentinel.sol`
## Vulnerability Description
The Wildcat protocol uses `CREATE2` to deploy contracts at deterministic addresses. Before deployment, the protocol checks if a contract already exists at the target address by comparing its `codehash` to `bytes32(0)`.
Technically, the Ethereum Virtual Machine (EVM) returns `0x0` for an address's codehash only if the account is **completely empty** (no code, no nonce, and no balance). If an account has a balance (e.g., 1 wei) but no code (an EOA or a pre-funded address), its codehash is returned as the Keccak-256 hash of empty data: `0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470`.
Because the protocol only checks for `bytes32(0)`, any address that has received even 1 wei will fail the check and be flagged as "already deployed." This prevents the factory from deploying necessary protocol infrastructure to that address.
## Exploitation
- **Status**: PoC available in audit findings; not reported as exploited in the wild.
- **Complexity**: Low
- **Attack Vector**: Network (Permissionless)
An attacker can calculate the future address of a borrower's `WildcatMarketController` (which is deterministic based on the borrower's address) and send 1 wei to that address. When the borrower later attempts to call `deployController()`, the transaction will revert with `ControllerAlreadyDeployed`, effectively bricking the protocol for that user.
## Impact
- **Confidentiality**: None
- **Integrity**: Low (Initialization state is corrupted)
- **Availability**: High (Permanent Denial of Service for specific borrowers or market deployments)
## Remediation
### Patches
The protocol team has confirmed the fix by updating the logic to check for both `bytes32(0)` and the empty Keccak hash.
### Workarounds
- Use `.code.length > 0` instead of `codehash` to check for existing deployments, as this correctly identifies if actual bytecode is present, regardless of account balance.
## Detection
- **Indicators of Compromise**: Repeated reverts of `deployController` or `deployMarket` calls for specific borrowers.
- **Detection Methods**: Monitor blockchain for `Transfer` events to predicted `CREATE2` addresses before they have been formally deployed by the Wildcat Factory.
## References
- **Vendor Advisory**: [code-423n4/2023-10-wildcat-findings - Issue #491](https://github[.]com/code-423n4/2023-10-wildcat-findings/issues/491)
- **EVM Technical Spec**: [EXTCODEHASH Behavior](https://ethereum[.]github[.]io/execution-specs/autoapi/ethereum/shanghai/vm/instructions/system/index[.]html#extcodehash)