Transfer Assignment

Almost good @bargerin, the problem is, since you are not updating the balance after or before the transfer of the amount, the balance of the user will always be the same, that way, it does not matter how many funds does it have, you can drain the entire contract through 1 user because its balance never decrease.

By just adding balance[msg.sender] -= amount; before or after the transfer (i recommend before), you will easily update the balance of the user and secure that it cant drain more than what it have.

Carlos Z

2 Likes
//SPDX-License-Identifier: Unlicensed

pragma solidity 0.7.5;

contract Bank{

mapping (address => uint) balance; //This mapping defines address as key and Ether Balance Value

/*@dev An event "accountData" has been created to log changes on balances it is 
emitted under the deposit and withdrawal function to log changes */


event accountData(address reciever, uint amountChange); 

address owner; //state variable that define owner 

modifier onlyOwner {
    require(msg.sender == owner,"Only Owner can execute transaction"); //Only owner execution
    _; //excutes the function on function body

}

constructor(address _owner) {
    owner = _owner; //Called before contract execution to define owner constructor 

}

function deposit() public payable returns(uint) {
    balance[msg.sender] += msg.value; //Adds amount
    uint amount = msg.value;
    emit accountData(msg.sender, amount); 
    return balance[msg.sender]; //Returns balance

}


function withdrawFunds(uint amount) public payable returns(uint) {

    require(balance[msg.sender] >= amount,"Insufficient Balance, please check that you have enough funds");
    uint previousBalanceNumber = balance[msg.sender];
    balance[msg.sender] -= amount; //Decreasing the balance
    msg.sender.transfer(amount); //This function will allow the withdrawal to happen
    assert(balance[msg.sender] == previousBalanceNumber - amount); //Just a Random check
    emit accountData(msg.sender,amount); //Will emit a log from the event parameters
    return balance[msg.sender];


}

function transferFunds(address recipient, uint amount) public {


    require(balance[msg.sender] >= amount,"Not enough funds to excute transactions");
    require(msg.sender != recipient, "One cannot transfer funds to their own address"); 
    _transferFunds(msg.sender,recipient,amount);

}



function _transferFunds(address from, address to, uint amount) private {
    balance[from] -= amount;  //This function will decrease balance from sender
    balance[to] += amount; //This function will increase the ether balance to reciever 

}

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

}

Here is my solution to the assignment, however I am confused as to how to implement
msg.sender.transfer(amount) on the withdrawal function on the 0.8.7 complier; it returns:

TypeError: "send" and "transfer" are only available for objects of type "address payable", not "address".
--> payable functions/Transfer_Assignment.sol:42:5:
|
2 Likes

Solution:

    
    function withdraw(uint amount) public returns (uint) {
        require(balance[msg.sender] >= amount, "Your size is not size");
        balance[msg.sender] -= amount; // update balance after withdraw
        msg.sender.transfer(amount); // execute the withdraw
        return balance[msg.sender];
    }

2 Likes

solution

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

    require(balance[msg.sender] > amount,"No suficient balance");

    msg.sender.transfer(amount);

    balance[msg.sender] -= amount;

    return balance[msg.sender];

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

In this code, if the transfer functions fails for some reason, would the whole function execution done till that point get reverted( in this case, will balance[msg.sender] -= amount; get reverted)

2 Likes

function withdraw(uint amount) public returns (uint){
uint previousSenderBalance = balance[msg.sender]
// msg.sender is already a payable address
require(balance[msg.sender] >= amount)
msg.sender.transfer(amount);
assert(balance[msg.sender] == previousSenderBalance – amount);
return balance[msg.sender];

}
// OR if address is not msg.sender

function withdrawTo(uint amount, address indexed sendTo) public returns (uint){

address payable sendTo = 0x34gd………;
uint previousSenderBalance = balance[msg.sender];
uint previousRecieverBalance = balance[sendTo]; 
require(balance[msg.sender] >= amount);
toSend.transfer(amount);
    assert(balance[toSend] == previousSenderBalance + amount);
    assert(balance[msg.sender] == previousRecieverBalance – amount);
    return balance[msg.sender];

}

2 Likes
> function withdraw(uint amount) public returns(uint) {
> 
>       require(amount<= balance[msg.sender],"not enough moneyy");
> 
>       msg.sender.transfer(amount);
> 
>       balance[msg.sender]-=amount;
> 
>       return balance[msg.sender];
> 
>     }

Seem to be ok like this

2 Likes
pragma solidity 0.7.5;

contract Bank {
    mapping(address=>uint) balance;
  
    event depositMade(uint amount, address indexed recipient);

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

    function withdraw(uint amount) public returns (uint) {
        require(balance[msg.sender] >= amount, "Cannot withdraw more than your total balance");
        
        msg.sender.transfer(amount);

        balance[msg.sender] -= amount;

        return balance[msg.sender];
    }

    function getBalance() public view returns(uint) {
        return balance[msg.sender];
    }
}
2 Likes
function withdraw(uint amount) public returns(uint){
    
    require(balance[msg.sender] >= amount);
    balance[msg.sender] -= amount;
    msg.sender.transfer(amount);
   
    return balance[msg.sender];
    
}
2 Likes
function withdraw(uint amount) public returns (uint) {
        require(balance[msg.sender] >= amount, "balance too low");
        balance[msg.sender] -= amount;
        msg.sender.transfer(amount);
        return balance[msg.sender];    
    }
2 Likes

add the line

require(balance[msg.sender] >= amount, “balance not sufficient”);

into the withdraw function

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

yeah @carlos is correct msg.sender needs to be wrapped in payable keyword payable(msg.sender) it used to not be like this in older versions not sure exactly which one but its in and around the 6 ot 7 version. but yeah usually just better to always wrap in payable

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

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

            //update user balance before withdrawal from contract
            	balance[msg.sender] -= amount;
            	msg.sender.transfer(amount);

            	return balance[msg.sender];

	}
2 Likes

First thought was this…

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

but then I thought… could I do something like this?

modifier atomicWithdrawal(amount) {
	require(balance[msg.sender] >= amount, "foobar");
	_; //run the function
    assert(balance[msg.sender] == (ogBalance - amount), "foobar");
}

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

Would value some feedback from instructors on how I structured the assertion. Can it be nested into the modifier like that? Any pitfalls in my approach?

1 Like

Also, just a little feedback. Not sure if it was just me but I felt a bit confused by this question:

Why is it useful to have a balance variable in our contract?

  • So that we as developers can check the balance of our contract
  • So that other people can check the balance of our contract
  • So that our contract can’t spend more than it owns
  • So that our contract can query for its own balance

I recall balance[msg.sender] being most useful for updating individual balances, and the instruction was to remember specifically that it isn’t for the contract’s balance, but the individual contributions. This prevents someone from withdrawing more than they invested, etc. Am I just reading the question wrong or something?

This will not work, the keyword _ will end the modifier execution, so the assert in any case should be inside the same function that needs the assertion, not outside of it.

assert is used to verify that a modification on a variable’s value is calculated has expected, so it should be defined and executed after the modification.

Carlos Z

 function withdraw(uint amount) public returns(uint){
        require(balance[msg.sender] >= amount, "Balance insufficient"); //constrains withdrawal amount to the user balance
        msg.sender.transfer(amount);
        balance[msg.sender] -= amount; //adjusts the value stored in the contract
        return balance[msg.sender];
    }
1 Like