Troubles with my Bank Contract

Here is my function for transfer on my bank contract. For some reason, my function keeps getting reverted on the first require statement even though I have sufficient funds. I have doubled checked that I deposit the ethereum and everything and have proper funds and copy it right but something keeps failing. Any ideas what is wrong?

    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);
        
        governmentInstance.addTransaction(msg.sender, recipient, amount);
        
        emit balanceTransferred(amount, recipient);
        
        assert(balance[msg.sender] == previousSenderBalance - amount);
        
    }

Here is what the error is saying:
transact to Bank.transfer errored: VM error: revert. revert The transaction has been reverted to the initial state. Note: The called function should be payable if you send value and the value you send should be less than your current balance. Debug the transaction to get more information.

1 Like

Hi there! My guess is that you should declare your function as payable.

function transfer(address recipient, uint amount) public payable {…}

Check it out:

#6 Payable Functions in Solidity β€” Smartcontract β€” Ethereum | by Rangesh Sripathi | Medium

https://ethereum.stackexchange.com/questions/20874/payable-function-in-solidity

Multiple things could be the issue here. Make sure that you have the latest version deployed. Also, can you get the balance back that you deposited? Please post your whole contract, so we can see all the other functions too. You do not have to declare your transfer function payable here @FranciscoNeto , as we are not sending ether, but only adjusting balances inside the mapping. So basically we are only changing numbers, but are not sending real ETH when transferring inside our bank contract. Only the deposit and the withdraw function do that and therefore need to be payable. I hope this makes sense.

1 Like

Hi @DJaySplash

For some reason, my function keeps getting reverted on the first require statement even though I have sufficient funds.

If your function reverts to the first require require(balance[msg.sender] >= amount, "Balance not sufficient"); it means that you don’t have enough tokens in the balance mapping.
You also write the following:

I have doubled checked that I deposit the ethereum and everything and have proper funds

But if you work with ERC tokens, that balance should be the ERC balance.

Can you post your full code and provide step by step how to replicate the issue?

@Bhujanga what you said is correct, just a clarification here:

Only the deposit and the withdraw function do that and therefore need to be payable.

Only the deposit function has to be payable. You use payable when a function has to receive ether :slight_smile:

Cheers,
Dani

1 Like

True, thanks for making this clear. :pray:

Thanks! I got you, it makes totally sense.

1 Like
pragma solidity 0.7.5;

import "./Ownable.sol";
import "./Destroyable.sol";

interface GovernmentInterface{
    function addTransaction(address _from, address _to, uint _amount) external;
}

contract Bank is Ownable, Destroyable {
    
    GovernmentInterface governmentInstance = GovernmentInterface(0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB);
    
    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 onlyOwner returns (uint) {
        require(amount <= balance[msg.sender]);
        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);
        
        governmentInstance.addTransaction(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;
    }
}

Here is the full code

Hey @DJaySplash

Please provide also:

Ownable.sol
Destroyable.sol
The government contract

Also the exact steps to reproduce the issue.

Regards,
Dani

contract Ownable{
   address internal owner; 
   
       modifier onlyOwner{
        require(msg.sender == owner);
        _;
    }
    
        constructor(){
        owner = msg.sender;
    }
}
import "./Ownable.sol";

contract Destroyable is Ownable {
    function endIt() public onlyOwner {
        address payable owner;
        owner = msg.sender;
        selfdestruct(owner);
    }
}
pragma solidity 0.7.5;

import "./Ownable.sol";
import "./Destroyable.sol";

interface GovernmentInterface{
    function addTransaction(address _from, address _to, uint _amount) external;
}

contract Bank is Ownable, Destroyable {
    
    GovernmentInterface governmentInstance = GovernmentInterface(0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB);
    
    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 onlyOwner returns (uint) {
        require(amount <= balance[msg.sender]);
        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);
        
        governmentInstance.addTransaction(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;
    }
}

Government Contract

pragma solidity 0.7.5;

contract Government{
    
    struct Transaction{
        address from;
        address to;
        uint amount;
        uint transactionID;
    }
    
    Transaction[] transactionLog;
    
    function addTransaction(address _from, address _to, uint _amount) external {
        transactionLog.push( Transaction(_from, _to, _amount, transactionLog.length) );
    }
    function getTransaction(uint _index) public view returns(address, address, uint) {
        return(transactionLog[_index].from , transactionLog[_index].to, transactionLog[_index].amount);
    }
}

The program reverts when I try to transfer funds.

I realized my mistake I was copying the wrong address for GovernmentInterface!

Thank you for the patience and help!

1 Like