Transfer Assignment

Hi @Samuel1

No need to use caps I always read all your messages :slight_smile:
Also please always report the error message returned by the compiler so that we can help you quickly.

In this case I am pretty sure that the error is here:
msg.sender.transfer(amount);

For Solidity 0.8, msg.sender is not considered payable by default anymore, therefore you have to cast it to payable in order to be able to call the method .transfer().

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

Give it a try,
Dani

I used 0.8.2 which is why I have payable(msg.sender).transfer(amount);. I checked the solidity docs and found this solution. If there is a better way please let me know. I’m still not sure where these error messages such as “Balance not sufficient” are displayed.

pragma solidity 0.8.2;

contract Bank {
    mapping(address => uint) balance;
    
    address owner;
    
    event depositDone(uint amount, address indexed depositedTo);
    
    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) {
        require(balance[msg.sender] >= amount, "Balance not sufficient");
        payable(msg.sender).transfer(amount);
        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 not sufficient");
        require(msg.sender != recipient, "Don't transfer money to yourself");
        
        uint prevSenderBalance = balance[msg.sender];
        
        _transfer(msg.sender, recipient, amount);
        
        assert(balance[msg.sender] == prevSenderBalance - amount);
    }
    
    function _transfer(address from, address to, uint amount) private {
        balance[from] -= amount;
        balance[to] += amount;
    }
}

Thanks for the advice !

pragma solidity 0.7.5;
contract myfirstbank {

mapping (address =>uint) balance;
balance[msg.sender] amount

function withdraw (uint amount) public returns uint {
require (balance [msg.sender] => amount “not enough funds”;

}

function deposit (uint amount) public returns uint{
require msg.sender.transfer(amount);
return balance[msg.sender];

}

*is wrong but i am new to all these and i need practice.Just post it to see what is my faults

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

Hi @Duende

Please check this FAQ that will guide you to post readable code in the forum: FAQ - How to post code in the forum

Let’s consider your code:

pragma solidity 0.7.5;
contract myfirstbank {

    mapping (address =>uint) balance;
    balance[msg.sender] amount
    
    function withdraw (uint amount) public returns uint {
        require (balance [msg.sender] => amount “not enough funds”;
    }
    
    function deposit (uint amount) public returns uint{
        require msg.sender.transfer(amount);
        return balance[msg.sender];

}

Not sure what you meant to do this this line:

balance[msg.sender] amount
  • amount is not defined;
  • the syntax is wrong as balance[msg.sender] does not point to a struct that has a property called amount, also the ; is missing at the end of the line.
    function withdraw (uint amount) public returns uint {
        require (balance [msg.sender] => amount “not enough funds”;
    }

The function correctly checks that the balance of msg.sender is higher than the amount that msg.sender wants to withdraw, but then nothing happens in the function.
There is a syntax error in the require statement because you are missing the closing ).

 function deposit (uint amount) public returns uint{
        require msg.sender.transfer(amount);
        return balance[msg.sender];

The function deposit should payable because you want to send Ether to it.
The function deposit should not transfer amount to msg.sender, you want to do that in the withdraw function.
There is a syntax error because you did not close the final }.

You should also increase and decrease balance[msg.sender] in your deposit and withdraw functions.

Check it out and let me know :slight_smile:

Happy learning,
Dani

1 Like

Here is my solution. I have few questions though.

  1. I wanted for user to do withdraw input in Ether (not in Wei because it is pretty much impractical). So I did it with “uint amountInWei = amountInEther * 1e18;”. Is there some other way? For example some global variable in unit Ether? I didn’t find it.

  2. if I have the conversion part “uint amountInWei = amountInEther * 1e18;” above the require part, so when require is not met, does it return gas also for the conversion part? Or does the require need to be always on the first line in a given function? Thanks.

    function withdraw(uint amountInEth) public returns(uint){
        uint amountInWei = amountInEth * 1e18;
        require(balance[msg.sender] >= amountInWei, "You don't have enough funds");
        uint previousBalance = balance[msg.sender];
        msg.sender.transfer(amountInWei);
        balance[msg.sender] -= amountInWei;
        assert(balance[msg.sender] == previousBalance - amountInWei);
    }
1 Like

Make sure that the user can not withdraw more than their balance
require(balance[msg.sender] >= amount, “Unsufficient balance” );
Correctly adjust the balance of the user after a withdrawal
balance[msg.sender] -= amount;

function withdraw(uint amount) public{
        require(balance[msg.sender] >= amount, "Not enough dough!" );
        msg.sender.transfer(amount);
        balance[msg.sender] -= amount;
}

With assert and return value, but this costs more gas when I tried it.

function withdrawOtherWay(uint amount) public returns(uint){
       require(balance[msg.sender] >= amount, "Not enough dough!" );
       uint senderBalance = balance[msg.sender];
       msg.sender.transfer(amount);
       balance[msg.sender] -= amount;
       assert(balance[msg.sender] == senderBalance - amount);
       return balance[msg.sender];
}
2 Likes

The solution was in the previous video!

pragma solidity 0.7.5;

contract Bank {

mapping(address => uint) balance;
address owner;

event depositDone(uint amount, address indexed depositedTo);

constructor (){
owner = msg.sender;

}

modifier onlyOwner {
require(msg.sender == owner);
_;

}

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){

 msg.sender.transfer(amount);

}

function getbalance() public view returns (uint){

 return balance [msg.sender];

}

function transfer (address recipient, uint amount) public {
//check sender balance

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); 

//event logs and further checks

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

}

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

}

Hi @Tomahawk

You should not use amount in ether as parameter but the amount in wei.
Keep in mind that solidity only uses uint, no decimals.

Regards,
Dani

1 Like

Hey @Tesh

Good job!
Please next time follow this faq to post readable code in the forum :slight_smile:
https://forum.ivanontech.com/t/faq-how-to-post-code-in-the-forum/35357/3

Cheers,
Dani

Oh right, I did test it with decimals now and it does not work. Good point. Thanks!

So if you have for example uniswap, you can put decimals on frontend, but I guess it converts to wei before solidity code start working with it. Right?

2 Likes

That is correct indeed!

1 Like

just look at a uniswap transaction :

https://etherscan.io/tx/0x15fcc5d1039afe29692982c60b460e946874aab7a983d741f5a98d772fbd9172

go to “input data” and click “decode input data”

you’ll see the input is a uint256 so I guess every conversion is done in the frontend/dapp

3 Likes

Done as following :

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

I noted that in Solidity v0.8.3, “transfer” doesn’t work on msg.sender, it requires the address to be “payable”. I don’t know yet how I can do that but will try it later.

2 Likes

All righty, here’s my code, followed by a quick question below:

    event depositTx(uint amount, address indexed depositedTo);
    event transferTx(uint amount, address indexed sentTo);
    
    function deposit() public payable returns(uint) {
        balance[msg.sender] += msg.value;
        emit depositTx(msg.value, msg.sender);
        return balance[msg.sender];
    }
    
    function withdrawal(uint _amount) public payable returns(uint) {
        require(_amount <= balance[msg.sender]);
        msg.sender.transfer(_amount);
        balance[msg.sender] -= _amount;
        emit transferTx(_amount, msg.sender);
        return(_amount);
    }

I’ve included the events and deposit() because I’m not understanding why my emit call in withdrawal() is not writing to the log. I see a log entry when I run deposit() but not when I run withdrawal(). Any thoughts? I can’t figure out the discrepancy.

Cheers!

That’s an odd change. I’m wondering how you declare msg.sender as payable, that seems very important to know.

I looked up on Google and found this :

https://ethereum.stackexchange.com/questions/94707/msg-sender-not-address-payable-solidity-0-8-2

Referencing to some of the latest changes in Solidity :

https://docs.soliditylang.org/en/v0.8.2/080-breaking-changes.html#how-to-update-your-code

2 Likes
 function withdraw(uint amount) public returns (uint){
        require (balance[msg.sender] >= amount, "Insufficient Funds"); //checks user's balance
        balance[msg.sender] -= amount; //subracts amount from user balance
        msg.sender.transfer(amount);  //tranfers the amount
        return balance[msg.sender]; //returns updated balance after transfer
    }    

1 Like

I have a Remix question that I will just post here!

How do I get the files to more permanently save?
Sometimes I close and reopen my browser and my helloworld.sol file is still there and sometimes it is not and I have to completely start over.