Hi @WMXgTW6wh,
You have added all of the additional lines of code needed to solve the problem with the withdraw function
The problem with it is the two lines of code youâve added for the assert() statement. You are saving the userâs balance to the local variable after youâve reduced it for the withdrawal amount, and so youâre not saving the previous balance. This means that, if the require() statement evaluates to true and revert isnât triggered for an insufficient balance, then assert() will always fail, instead.
This error is caused by your deposit() function being incorrectly coded. You need to go back and re-watch the video where you are shown how to code this function, before the assignment. You have some code left over from the previous addBalance function, which isnât correct now that we are depositing ether into the contract, and not just an amount
which represents some other kind of value of our own creation.
The deposit() function is receiving ether from the callerâs external address, so that it can be added to the contract address balance. To perform this kind of value transfer you need to send an amount in wei to the function which is receiving it; but this isnât passed as an argument in the usual way. In Remix we do this by entering the value we want to deposit in the Value field in the Deploy & Run Transactions panel. You can use the dropdown on the right to select the uints of value you want the number youâve entered to represent (ether or wei etc.). The integer passed to the smart contract and processed by the Solidity code will be treated as units of wei, but the dropdown just saves us having to input a whole lot of 0âs. Marking a function payable
enables it to receive ether. This then happens automatically without having to include a parameter for this value. In the same way that we can reference the callerâs address with msg.sender
(without having to include an address parameter), we can use msg.value
to reference a wei value which is sent to a function by the caller (as long as the function has been marked payable).
If you havenât done this when calling deposit(), no ether will have been added to the contract balance, and msg.value
will be zero. When you make a value transfer in the way Iâve explained above, you will see the callerâs address balance (the one showing in the Account field) is reduced by that amount, and the callerâs individual balance in the mapping in the Bank contract increases by the same amount.
In the withdraw() function, we use the pre-defined transfer()
function to perform a value transfer from the contract address balance to the callerâs external address.
<address payable>.transfer(uint256 amount)
The amount in wei deducted from the contract balance, and transferred out of the contract, will be the amount requested by the caller of the withdraw() function and input as the amount
parameter. This input amount
is then passed to transfer()
within the function. Because transfer()
is called on the callerâs own external address, the amount input by them is transferred to their external address. The amount
parameter also needs to be referenced within withdraw() in the line of code which reduces the userâs individual account balance in the mapping (in order to track their own individual share of the total ether held in the contract). This is why the withdraw() function needs an amount parameter, whereas the deposit() function doesnât.â msg.value
is only available in payable functions, and references the value received by the contract, not sent from it.
Let me know if anything is unclear about how you need to correct your code, or if you have any further questions. 