function withdraw(uint256 _amount) external {
balances[msg.sender] -= _amount;
(bool success, ) = payable(msg.sender).call{value: _amount}("");
}
If the low-level .call()
is unsuccessful, the value of success
is set to false
but that doesn't revert the whole transaction. So the balances
value would be reflected even though the payment didn't go through.
You can add a require()
condition to check the result of the payment. This will make the parent transaction fail if the internal transaction fails.
(bool success, ) = payable(msg.sender).call{value: _amount}("");
require(success);
Or you can use the .transfer()
function (member of address payable
, do not confuse with token transfers) that also fails the parent transaction if the internal transaction fals:
function withdraw(uint256 _amount) external {
balances[msg.sender] -= _amount;
payable(msg.sender).transfer(_amount);
}