See what ContractScan finds — no login or file upload required.
withdraw() function sends ETH to the caller before updating the balance (CEI pattern violation). An attacker can re-enter the function via a malicious fallback and drain the contract.
Vulnerable pattern detected:
function withdraw() public {
(bool ok,) = msg.sender.call{value: balances[msg.sender]}("");
require(ok);
balances[msg.sender] = 0; // ← updated AFTER external call
}
Fix (Checks-Effects-Interactions pattern):
function withdraw() public {
uint amount = balances[msg.sender];
balances[msg.sender] = 0; // ← update state FIRST
(bool ok,) = msg.sender.call{value: amount}("");
require(ok);
}emergencyWithdraw() function has no onlyOwner or access modifier. Any address can drain all funds from the contract.call() is not consistently validated across all code paths. A failed ETH transfer will silently continue execution.Static analysis powered by Slither (© Trail of Bits, AGPL-3.0)