Hi @jeanphi,
Looking now at your solution to this Transfer Assignment, I can clearly see where you misunderstood certain key concepts surrounding the transfer of ether between addresses, and how this is different to how a contract records its users individual balances (which could refer to either tokens, or the user’s share of the contract’s total ether balance).
After having written most of this post, I’ve just seen your reply in the other discussion topic, which seems to confirm that the information and explanations I’ve already given you there have now resolved a lot of the issues with your solution for this Transfer assignment. But I’ll still give you a brief summary of the points that arise from this assignment, so you can check to make sure you now understand what you should have done differently and why
(1)
msg.value
references an ether value that is sent to a payable
function and is automatically added to the contract address balance. Your withdraw() function is therefore a strange combination of a deposit and a withdraw function, which requires the caller to send ether to the contract in order to make a withdrawal. But the amount withdrawn from the contract balance and added to the user’s external wallet balance will always be exactly the same amount that is deducted from the user’s external wallet balance and added to the contract balance — meaning that the overall net effect in terms of both parties’ ether balances is zero. However, even though both the contract balance and the user’s external wallet balance do not change, the user’s balance in the mapping is still reduced by the amount of ether sent and then received back. So after each withdrawal the user will have effectively received zero ether, but their “entitlement” to a share of the total funds held in the contract will have decreased, while the contract balance doesn’t decrease. So I’m sure you can see who ends up gaining from this!
(2)
The individual user balances for this contract, which are stored in the mapping, reflect ether transactions, not token transactions. That’s why it’s not appropriate to name the mapping something related to tokens. However, we could have a contract which transacts with tokens. For example, these could be ERC-20 or ERC-721 tokens. Such token contracts are built according to rigorous standards and specifications, and are much more complex than our initial, simple HelloWorld contract with the addBalance() and transfer() functions. But the underlying principle is the same. The functions that execute transactions with tokens, and which don’t involve the exchange of ether…
(i) do not need to be payable
(ii) do not not need to reference msg.value
(iii) do not need to use the address member <address payable>.transfer(uint256 amount)
… all of which are only relevant when we are performing transactions with ether.
You need to make a clear distinction between how we use Solidity to program (i) movements of ether (the currency of the Ethereum ecosystem) and (ii) movements of other units of value, such as tokens we have created, and which are governed by their own smart contracts.
(3)
(4)
I wouldn’t use the Storage contract template from Remix for this Bank contract, as it’s more complex than a simple storage contract. Also, the comments at the top of the Storge contract template aren’t relevant to this contract. I would call this contract Bank, or something similar, because that’s a good description of what the contract does.
(5)
Your moneyDeposited and moneyWithdrawn events and emit statements are both coded well enough to the extent that they will work. You have also placed the emit statements in the correct position within their respective function bodies. However, the following improvements can be made:
- As well as the deposit or withdrawal amount, both transactions involve another key piece of information — the address of the account holder who is either depositing or withdrawing ether. So this is also useful data to include in each event.
- It is helpful to add an identifier (a name) to each event argument (e.g.
_amount
or_withdrawnBy
etc., so that the data is easier to recognise and handle when it is logged or captured in the frontend of a dapp.
(5)
Finally, have a look at this post which explains the importance of the order of the statements within your withdraw function body.
I hope you find this a useful summary, just to check that you have now understood all of these issues and concepts, or that you at least have a better understanding. You will need to feel comfortable with these aspects of Solidity before moving on to the 201 course, otherwise things could get a bit
Anyway, just let me know if you have any more questions