An excellent solution @Samm
You have added all of the additional lines of code needed to solve the problem with the withdraw function, and they are in the correct order to reduce security risk:
- check inputs (require statements)
- effects (update the contract state)
- external interactions
Just as you have done, itâs important to modify the contract state for the reduction in the balanceâŠ
balance[msg.sender] -= amount;
before actually transferring the funds out of the contract to the external wallet addressâŠ
payable(msg.sender).transfer(amount);
⊠just in case there is an attack after the transfer, but before the state is modified to reflect this operation. The type of attack this specific order of operations prevents is a re-entrancy attack, and this is covered in detail in the Smart Contract Security course. But itâs great youâre already getting into good habits in terms of best practice in this area
You need to bear in mind that the syntax taught in this course is for Solidity v0.7. Thatâs absolutely fine to use v0.8, but one of the changes in syntax from v0.8 is that msg.sender
is no longer a payable address by default, and so when it needs to refer to a payable address, it needs to be explicitly converted. As you have discovered, one of the ways to do this is withâ payable(<address>)
You can also do it the way you initially thought of, by assigning msg.sender
to a local payable-address variable, as follows:
address payable receiver = payable(msg.sender);
receiver.transfer(amount);
But as you can see, we would still have to explicitly convert msg.sender
in order to be able to assign it to a payable address variable, so in our particular case it ends up being much less concise.
If you are using Solidity v0.8 for your assignments, then include that at the top of your code, so we know what syntax we are reviewing and checking for.
The solidity compiler will always generate an error when your syntax needs to be changed for v0.8, and the error message will tell you why, and often what you should change it to. In fact, msg.sender
changing from payable to non-payable by default could well be the only change in syntax from v0.7 to v.0.8 that you will face during this initial course. So it shouldnât cause much of an issue for you.
In order to receive ether, an address needs to be payable
, so this is why in Solidity v0.8 you have to convert msg.sender
when using it as the address inâŠ
<address payable>.transfer(uint256 amount)
The withdrawal event (with corresponding emit statement), which youâve added, is also appropriate and well coded. The emit statement will log relevant information when a call to the withdraw function has executed successfully.
Iâm not too sure what you mean by this to be honest. What exactly did you add to the contract header?
contract Bank { // This is the contract header. Is this actually what you mean?
Just let me know if you have any questions