Transfer Assignment

Reduce the amount from msg.sender balance

Return the new balance.

function withdraw(uint amount) public returns (uint) {
        require(balance[msg.sender] >= amount);
        balance[msg.sender] -= amount;
        
        msg.sender.transfer(amount);
        
        return balance[msg.sender];
        
    }
1 Like

So basically if we think about it logically we cant withdraw funds that we dont have. Therefore we need to check our balance and compare it to the withdrawal amount. we can use require. Thats pretty much it.

Just for the sake of taking in the course material i threw in an assert to make sure the final balance after withdrawal is equal to the previous balance minus the amount but not sure if this is unnecessary code in this particular instance but good practice opportunity

 function withdraw(uint amount) public returns (uint)
{
    //we need to check the error handling to make sure that we cannot
    //withdraw more money than we tohave
    
    require(balance[msg.sender] >= amount, "Insuficient funds");
    
    //here we can keep track of the balance before withdrawals
    uint balanceBeforeWithdrawal = balance[msg.sender];
    
    
    //we use the following notation for withdrawals
    msg.sender.transfer(amount);
    
    //once we have transfered we can update our balance and do a few another
    //sanity checks
    balance[msg.sender] = balance[msg.sender] - amount;

    //as a final prrof to make sure our code its ok we can assert to make sure
    //our balance is correct. Our balance must be equal to our previous balance
    //minus the amount
    assert(balance[msg.sender] == balanceBeforeWithdrawal - amount);
    
    //return the balance for viewing
    return balance[msg.sender];
}
2 Likes
pragma solidity 0.8.1;

contract Bank{
    
    mapping(address => uint) balance;
    address owner;
    
    event depositDone(uint amount, address indexed depositedTo);
    
    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }
    
    constructor(){
        owner = msg.sender;
    }
    
    function deposit() public payable returns(uint){
        
        balance[msg.sender] += msg.value;
        
        emit depositDone(msg.value, msg.sender);
        
        return balance[msg.sender];
    }
    
    function withdraw(uint amount) public returns (uint){
        require(balance[msg.sender]>=amount);
        
        address payable myAddress = payable(msg.sender);
        balance[msg.sender]-=amount;
        myAddress.transfer(amount);
        return balance[msg.sender];
    }
    
    function getBalance() public view returns (uint){
        return balance[msg.sender];
    }
    
    function transfer(address recipient, uint amount) public{
        require(balance[msg.sender] >= amount, "Balance not sufficient");
        require(msg.sender != recipient, "Don't transfer money to yourself");
        
        uint previousSenderBalance = balance[msg.sender];
        
        _transfer(msg.sender, recipient, amount);
        
        assert(balance[msg.sender] == previousSenderBalance - amount);
        // event logs and further checks
    }
    
    function _transfer(address from, address to, uint amount) private{
        
        balance[from] -= amount;
        balance[to] += amount;
        
    }
}
1 Like

Check if the balance of the sender is >= to amount they are requesting to withdraw using a require function before the proceeding code can be executed.

function withdraw(uint amount) public returns (uint) {
// Assignment solution
require(balance[msg.sender] >= amount, “Balance not sufficient”);
msg.sender.transfer(amount);
// Update users balance in the local mapping
balance[msg.sender] -= amount;
return balance[msg.sender];
}

1 Like
pragma solidity ^0.7.5;

contract Bank {
    
    mapping(address => uint) balance;
    
    address owner;
    
    event depositDone(uint amount, address indexed depositedTo);
    
    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }
    
    constructor() {
        owner = msg.sender;
    }
    
    function deposit() public payable returns (uint) {
        balance[msg.sender] += msg.value;
        emit depositDone(msg.value, msg.sender);
        return balance[msg.sender];
    }
    
    function withdraw(uint amount) public payable returns (uint) {
        require(amount <= msg.value);
        msg.sender.transfer(amount);
        return balance[msg.sender] -= amount;
    }
    
    function getBalance() public view returns (uint) {
        return balance[msg.sender];
    }
    
    function transfer(address recipient, uint amount) public {
        require(balance[msg.sender] >= amount, "Balance is not sufficient");
        require(msg.sender != recipient, "Please don't send money to yourself");
        
        uint previousSenderBalance = balance[msg.sender];
        
        _transfer(msg.sender, recipient, amount);
        
        assert(balance[msg.sender] == previousSenderBalance - amount);
    }
    
    function _transfer(address from, address to, uint amount) private {
        balance[from] -= amount;
        balance[to] += amount;
    }
    
}

Hey @kresna_sucandra

    function withdraw(uint amount) public payable returns (uint) {
        require(amount <= msg.value);
        msg.sender.transfer(amount);
        return balance[msg.sender] -= amount;
    }

Withdraw functions do not receive ether therefore it should not be payable.
It also wont have a msg.value.

function withdraw(uint amount) public payable returns (uint) {
       require(amount <= msg.value);

With this statement you are basically requiring the user to deposit ether, then you check if the ether he is depositing are bigger than the amount he wants to withdraw.

Double check this function and let me know if you need help.

Cheers,
Dani

1 Like
function withdraw (uint amount) public returns (uint){
    require (amount <= balance[msg.sender] , "You Don't Have That Much Eth.");


    msg.sender.transfer (amount);
    }

Thank you, Dani. I found my solution was wrong. Thank you for the clarification.

1 Like
pragma solidity 0.7.5;

contract Bank {
    
    mapping(address => uint) balance;
    
    event depositDone(uint amount, address indexed depositedTo);
    
    function deposit() public payable returns (uint)  {
        balance[msg.sender] += msg.value;
        emit depositDone(msg.value, msg.sender);
        return balance[msg.sender];
    }
    
    function withdraw(uint amount) public returns (uint){
        require(balance[msg.sender] >= amount);
        balance[msg.sender] -= amount;
        msg.sender.transfer(amount);
        return balance[msg.sender];
    }
    
    function getBalance() public view returns (uint){
        return balance[msg.sender];
    }
    
    function transfer(address recipient, uint amount) public {
        require(balance[msg.sender] >= amount, "Balance not sufficient");
        require(msg.sender != recipient, "Don't transfer money to yourself");
        
        uint previousSenderBalance = balance[msg.sender];
        
        _transfer(msg.sender, recipient, amount);
                
        assert(balance[msg.sender] == previousSenderBalance - amount);
    }
    
    function _transfer(address from, address to, uint amount) private {
        balance[from] -= amount;
        balance[to] += amount;
    }
    
}

I have a question about above solution ,

Does the " msg.sender.transfer (amount); " work by itself or it works because there is a transfer function in the contract ?
is the .transfer refering to transfer function or it is a direct way to transfer to recipient address ?

Please advise
Cheers

pragma solidity 0.7.5;

contract Bank {

mapping(address => uint) balance;

event depositDone(uint amount, address indexed depositedTo);

function deposit() public payable returns (uint)  {
    balance[msg.sender] += msg.value;
    emit depositDone(msg.value, msg.sender);
    return balance[msg.sender];
}

function withdraw(uint amount) public returns (uint){
    require(balance[msg.sender] >= amount);
    balance[msg.sender] -= amount;
    msg.sender.transfer(amount);
    return balance[msg.sender];
}

function getBalance() public view returns (uint){
    return balance[msg.sender];
}

function transfer(address recipient, uint amount) public {
    require(balance[msg.sender] >= amount, "Balance not sufficient");
    require(msg.sender != recipient, "Don't transfer money to yourself");
    
    uint previousSenderBalance = balance[msg.sender];
    
    _transfer(msg.sender, recipient, amount);
            
    assert(balance[msg.sender] == previousSenderBalance - amount);
}

function _transfer(address from, address to, uint amount) private {
    balance[from] -= amount;
    balance[to] += amount;
}

}

1 Like

I modified the withdrawal function and added an event to log withdrawals:

…

event withdrawal(address indexed accountHolder, uint amount);

…

function withdraw(uint amount) public returns(uint){
        require(balance[msg.sender] >= amount, "You cannot withdraw more than your balance.");
        payable(msg.sender).transfer(amount);
        balance[msg.sender] -= amount;
        emit withdrawal(msg.sender, amount);
        return balance[msg.sender];

…

1 Like
type or ppragma solidity 0.7.5;

contract Bank {


mapping(address => uint) balance;
address owner;
modifier onlyOwner {
require(msg.sender == owner);
_;
} 
event depositDone(uint amount, address indexed depositedTo);

function deposit() public payable returns (uint)  {
    balance[msg.sender] += msg.value;
    emit depositDone(msg.value, msg.sender);
    return balance[msg.sender];
}

function withdraw(uint amount) public onlyOwner returns (uint){
    require(balance[msg.sender] >= amount);
    msg.sender.transfer(amount);
    return balance[msg.sender];
}

function getBalance() public view returns (uint){
    return balance[msg.sender];
}

function transfer(address recipient, uint amount) public {
    require(balance[msg.sender] >= amount, "Balance not sufficient");
    require(msg.sender != recipient, "Don't transfer money to yourself");
    
    uint previousSenderBalance = balance[msg.sender];
    
    _transfer(msg.sender, recipient, amount);
    

    assert(balance[msg.sender] == previousSenderBalance - amount);
}

function _transfer(address from, address to, uint amount) private {
    balance[from] -= amount;
    balance[to] += amount;
}
}aste code here
1 Like

Hi @M.K

.transfer() is a method of any payable address therefore is not related to the transfer function declared in your contract.

Cheers,
Dani

1 Like

event withdrawals (uint AmountWithdraw, address WithdrawBy);

function withdraw(uint amount) public returns(uint) {
require(Balance[msg.sender] >= amount, “Not enough money to withdraw this amount!”);
Balance[msg.sender] -= amount;
msg.sender.transfer(amount)
emit withdrawals (amount, msg.sender);
}

1 Like

Here is my answer:

function withdraw(uint amount) public returns (uint){
//check balance of msg.sender
require(balance[msg.sender] >= amount, “Balance not suficient”);
msg.sender.transfer(amount);
//reduce balance of mapping
balance[msg.sender] -= amount;
return balance[msg.sender];
}

1 Like

Hi @bfleming98,

The require statement you’ve added is correct :ok_hand: but you are missing 2 other important lines of code:

  • When you deploy your contract and call your withdraw function as it is, you will notice that the sender’s address receives the requested withdrawal amount, but their balance in the mapping is not reduced! I’m sure you can see that this is another very serious bug! How would you correct this? If you can’t work this out yourself, you’ll find the answer by taking a look at some of the other posts in this topic.
  • Notice that the withdraw function header also includes returns(uint) . This is not mandatory to include, and the function can still operate effectively without returning a value. But as it’s been included in the function header, you also need to include a return statement in the function body.

Once you’ve had a go at making the above modifications, have a look at this post which explains the importance of the order of the statements within your withdraw function body.

Let us know if you have any questions about how to correct this, or if there is anything that you don’t understand :slight_smile:

Nice solution @Nelson1 :ok_hand:

You have included all of the additional lines of code needed to solve the problem with the withdraw function, and you have them all in an order that optimises security:

  1. check inputs (require statement)
  2. effects (update the contract state for reduction in balance)
  3. external interactions (perform the transfer of funds from the smart contract address to the external wallet address).

Notice that the withdraw function header also includes returns(uint) . This is not mandatory to include, and the function can still operate effectively without returning a value. But as it’s been included in the function header, you also need to include a return statement in the function body.

The additional event that you’ve added is also good. It emits and logs relevant information when a call to the withdraw function has executed successfully. Just remember that the convention is to start event names with a capital letter (e.g. event Withdrawal ), although your code does still work using a lower case letter. What is a problem, though, is writing the mapping name balance starting with a capital letter: Balance. If you have also used an upper case letter in your mapping name, then your code will work, but if you haven’t then it will throw an error. Remember that it’s standard practice to start variable names (including mappings and arrays) with a lower case letter. It’s just struct and event names that we start with a capital letter.

Your posted solution will also not execute, because you’ve missed off a semi colon at the end of one of your lines. You should format your code before posting it. This should also make it easier to spot any errors like the ones I’ve just mentioned.
Follow the instructions in this FAQ: How to post code in the forum

An excellent assignment solution @galgostark :muscle:

You have added all of the additional lines of code needed to solve the problem with the withdraw function.
Now have a look at this post which explains an important security modification that should be made to the order of the statements within your withdraw function body. I think you’ll find it interesting :slight_smile:

Just one final thing. Please format your code before posting it, so it’s clearer and easier to read. Follow the instructions in this FAQ: How to post code in the forum

Change the withdraw function to the following:

function withdraw (uint amount) public returns (uint){

   require(balance[msg.sender] >= amount);
   msg.sender.transfer(amount);
   balance[msg.sender] -= amount;
1 Like
    function withdraw(uint amount) public returns (uint) {
        require(balance[msg.sender] >= amount, "Balance not sufficient");
        msg.sender.transfer(amount);
        uint previousAmount = balance[msg.sender];
        balance[msg.sender] -= amount;
        assert(balance[msg.sender] == previousAmount - amount);
        return balance[msg.sender];

    }
1 Like