Transfer Assignment

Assert if the balance is bigger or equal than amount, then subtract the amount from balance[msg.sender]

pragma solidity 0.7.5;

contract Bank {
    
    mapping (address => uint) balance;
    address owner;

    event depositDone(uint amount, address depositedTo);
    event MoneyTransferred(address indexed transferredFrom,address indexed transferredTo, uint amount);

    modifier onlyOwner{
        require(msg.sender == owner);
        _; //run the function
    }
    
    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){
        assert(balance[msg.sender] >= amount);
        msg.sender.transfer(amount);
        balance[msg.sender] -= 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);

        emit MoneyTransferred(msg.sender, recipient, amount);
    }

    function _transfer(address from, address to, uint amount) private{
        balance[from] -= amount;
        balance[to] += amount;
    }
}
1 Like
    function withDraw(uint amount) public returns (uint){
        //check balance of msg.sender is sufficient.
        require(balance[msg.sender] >= amount, 
        "Insufficient Funds: Please enter withdrawal amount less or equal to your current balance"
        );
        msg.sender.transfer(amount);
        

        //ajust balance
        balance[msg.sender] -= amount;
    }

My solution to the transfer assignment:

pragma solidity 0.8.17;

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, "Not enough balance.");
        balance[msg.sender] -= amount;
        payable(msg.sender).transfer(amount);
        return balance.[msg.sender];
    } 

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

    function transfer(address recipiant, uint amount) public{
        
        require(balance[msg.sender] >= amount, "Balance too low");
        require(msg.sender != recipiant, "Can only transfer to other people");

        uint previousSenderBalance = balance[msg.sender];
        _transfer(msg.sender, recipiant, amount);
        
        assert(balance[msg.sender] == previousSenderBalance - amount);

    }

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

    }
}
1 Like

Hi guys!

Here is my solution to the assignment:

pragma solidity 0.8.7;

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

require (balance[msg.sender] >= amount, "insufficient balance");

balance[msg.sender] -= amount;

payable(msg.sender).transfer(amount);

return balance[msg.sender];

}

I received an error first when I tried to use just “msg.sender.transfer(amount)”.

Was there a recent update that requires payable in front of “msg.sender.transfer(amount)” ?

A bit confused about that part so please if somebody has more information please let me know.

1 Like

Hi @krille1

Yes, It seems like payable was added in the new solidity versions. I tested with 0.7.0 version which does not require marking the address as payable however the new versions require marking the address as payable.

1 Like

Hi @JohnVersus

Thanks a lot. Now it makes sence :slight_smile:

1 Like
function withdraw(uint amount) public returns (uint){
    require (amount<= balance[msg.sender]);
    msg.sender.transfer(amount)
}
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 getBalance() public view returns (uint){
        return balance[msg.sender];
    }

    function withdraw(uint amount) public returns (uint){
        require(balance[msg.sender] >= amount, "balance insufficient");
        balance[msg.sender] -= amount; //adjust balance answer
        msg.sender.transfer(amount);
    }
}

function withdraw(uint amount) public ownerWithdraw returns (uint) {
//error handling
require (balance[msg.sender] >= amount);
[msg.sender].transfer(amount);
}

There it goes:

function withdraw(uint amount) public returns (uint) {
        require(balance[msg.sender] >= amount, "You don't have that amount of ether!");
        balance[msg.sender] -= amount;
        msg.sender.transfer(amount);
        return balance[msg.sender];
    }

Just wanted to check if the 2 versions of the function withdraw would be “equivalent”, even if the first version (without require) is less efficient. Also, would it be possible to add some additional modifier to deal with the new require function (in the 2nd version)? My guess is that we would need to declare uint amount before this new modifier function but I am not sure how to do it nicely.

//Transfer Assignement
pragma solidity 0.7.5;

contract Bank {

    mapping(address => uint) balance;

    address owner;

    //event balanceAdded(uint amount, address depositedTo);
    event depositDone(uint  amount, address indexed depositedTo); 
    event transferDone(uint amount, address indexed sender, address indexed recipient);

    modifier onlyOwner { //help to save time and space
        require(msg.sender == owner); 
        _; //means run the function
    }

    constructor(){ 
        owner = msg.sender; //this way we define who the owner is (as the deployer of the contract)
    }

    function deposit() public payable returns (uint) { 
        balance[msg.sender] += msg.value;
        emit depositDone(msg.value, msg.sender);
        return balance[msg.sender];
    }
      //version without Error Handling
     function withdraw(uint amount) public returns(string memory){

        if(balance[msg.sender] >= amount){
            msg.sender.transfer(amount);
            balance[msg.sender] -= amount;
        }
        else{
            return "insufficient deposit";
        }  
    }

    //version with Error Handling
    function withdraw(uint amount) public {   
        require(
            balance[msg.sender] >= amount,
            "insufficient deposit");
        msg.sender.transfer(amount);
        balance[msg.sender] -= amount;
    }

    function getBalance() public view returns (uint) {
        return balance[msg.sender]; //returns balance in the smart contract
    }

    function transfer(address recipient, uint amount) public {
        //Check balance of msg.sender
        require(balance[msg.sender] >= amount, "Balance not sufficient");
        require(msg.sender != recipient, "Do not transfer money to yourself");
        
        uint previousSenderBalance = balance[msg.sender]; //this is a bit forced... will be different if we work with ETH
        
        _transfer(msg.sender, recipient, amount);

        //emit transferDone(amount, msg.sender, recipient);

        assert(balance[msg.sender] == previousSenderBalance - amount);
        //event Logs and further checks to be added later
    }
    //we create a private function that will manage the transfer
    function _transfer(address from, address to, uint amount) private {
        balance[from] -= amount;
        balance[to] += amount;
        //emit transferDone(amount, from, to);
    }
}
1 Like

Hi @fsicard

You can define a modifier like this to check the balance.

    modifier hasBalance(uint amount) { 
        require(
            balance[msg.sender] >= amount,
            "insufficient deposit");
        _; 
    }
    function withdraw(uint amount) public  hasBalance(amount) {   
        msg.sender.transfer(amount);
        balance[msg.sender] -= amount;
    }

Your withdraw function with if conditions will work for conditional transfer. But it will not throw an error when there is an insufficient balance. If there is no error thrown the transaction will get executed on the blockchain and gas will be consumed.
To avoid this unnecessary transaction we need to throw an error using require, so the transaction will be failed with an error when there is no sufficient balance.

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

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 guess I messed up, but I don’t know why or how :blush:

I tried to fix the error but I couldn’t, and finally I copied the code from the solution form, BUT I KEEPS GIVE ME THE SAME ERROR, for the WITHDRAW function (msg.sender.transfer(amount))

pragma solidity 0.8.18;

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); // **red underline indicates (TypeError: "send" and "transfer" 
       //are only available for objects of type "address payable", not "address".)**
        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;
    }
}

Hi @Ahmad_Abd_Allah

Update this line with payable (msg.sender).transfer(amount); you need to mark the address as payable in the latest solidity versions.

2 Likes
function withdraw(uint amount) public returns (uint) {
        require(balance[msg.sender] >= amount, "You cannot withdraw more than what you put in!");
        msg.sender.transfer(amount); 
        balance[msg.sender] = balance[msg.sender] - amount;
        return balance[msg.sender];
    }
mapping (address => uint) balance;

  address owner;

  event depositDone (uint amount, address indexed  addedBalance);

  event transferDone(uint amount, address indexed madeTransfer, 
  address indexed receivedTransfer);

  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, "You can't withdraw this amount");
    payable (msg.sender).transfer(amount);
    balance[msg.sender] -= amount;
    return balance[msg.sender];
  }

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

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

  uint SenderPreviousBalance = balance[msg.sender];

    _transfer (msg.sender, recipient, amount);

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

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

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

Added a require function that checks if the amount to withdraw is less that the sender’s 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];
    }