Hi @Naoki_Takahashi,
Withdraw function
balance[msg.sender] -= amount
;
return statement
You have the right idea with the sufficientAmount modifier, but you need to include an amount
parameter in the header, so that you can call the modifier in the withdraw function header with the amount the caller wants to withdraw, as follows:
modifier sufficientAmount(uint amount) {
require(balance[msg.sender] >= amount, "Not enough balance!");
_;
}
function withdraw(uint amount) public sufficientAmount(amount) returns(uint) { }
/* The value of the function's amount parameter is passed to the modifier
in order for the modifier to check that the withdrawal amount is not
greater than the caller's balance */
The compiler will generate a red error for your modifier, and the error message will state that there is an undefined identifier — this is the name amount
which needs to reference something (in this case a parameter uint amount
, which needs to be passed to the modifier).
Your withdrawDone event declaration is appropriate and well coded, except for the missing semi colon at the end of the statement, which will prevent your contract from compiling. The compiler should have generated a red error for this.
The corresponding emit statement should reference the amount
parameter, not msg.value
(which only references an ether/wei value received by a payable
function, such as the deposit function). The compiler will generate a red error for this too.
Also, events should only be emitted once all of the associated operations have been completed i.e. all of the necessary modifications have been made to the contract state, and any external interactions have been executed. You should, therefore, position your emit statement at the end of the function body, just before the return statement.
Once you have made these modifications to your withdraw function, have a look at this post which explains an important security modification that should be made to the order of 2 other statements in your withdraw function body.
You have put a lot of effort into your contract code as a whole, and also into the comments you have added to explain the purpose of certain lines of code. Here some additional comments about your code, and corrections you should make:
(1) You have a state variable deposited
, which isn’t used anywhere.
(2)
… the owner of the contract (not transaction).
(3)
… yes, and this transaction is deploying the contract, so this constructor sets the owner
state variable as the address which deploys the contract.
(4) The idea of this contract is to simulate a bank. So, it’s probably not such a good idea to restrict deposits to the contract owner (which you’ve done by applying the onlyOwner modifier to the deposit function). As anyone can transfer and withdraw funds, it would make more sense if anyone can deposit funds into the contract as well.
(5) Your transfer event and corresponding emit statement are both correctly coded, and the emit statement will log appropriate data when the transfer() function is successfully executed. But in general, an emit statement is probably better placed after an assert statement.
Where the deposit and withdraw functions both execute transactions that only involve 1 user address (the depositor or the withdrawer), the transfer function executes a transaction that involves 2 user addresses (the sender and the recipient). So, it would be useful to include the sender’s address, as well as the recipient’s address, within the data emitted for the transfer event.
(6) With reference to your sufficientAmount modifier, the point of writing a separate modifier to validate an input or restrict access to a function — instead of placing this code at the beginning of the function body — is to avoid code duplication by re-using the modifier. Adding your sufficientAmount modifier is a very good idea, because it can be used in both the withdraw() and the transfer() function; but you have missed the opportunity to use it in transfer(), which requires exactly the same input validation as withdraw().
Let me know if anything is unclear, or if you have any questions