Reentrancy in withdraw()
External call to msg.sender executes before the balance is updated, so a malicious receiver can re-enter withdraw() and drain the pool.
Generated repair · contracts/LendingPool.sol
function withdraw(uint256 amt) external {function withdraw(uint256 amt) external nonReentrant { require(balances[msg.sender] >= amt); balances[msg.sender] -= amt; (bool ok, ) = msg.sender.call{value: amt}(""); require(ok, "transfer failed"); balances[msg.sender] -= amt;}Why this fix
Applies checks-effects-interactions and adds a reentrancy guard. The state update now happens before value leaves the contract.
Verification
- Exploit no longer reproduces on fork
- Existing test suite passes (212)
- Gas delta +2.1%