1

I am writing a contract where I want to transfer money (present in the contract owners account and not the contract) to an account address passed to a function in the contract.

for some reason this code won't work

function payBill(uint value, address account) payable public {
account.transfer(value);
transactionCount += 1;
transactionAmount += value;

}

3
  • well, it won't compile as it stands... account needs to be of type address payable in order to expose the transfer method. – Zakalwe Feb 12 '20 at 9:06
  • Why do you want to write a contract function that does exactly what basic transfers do ? – Florian Castelain Feb 12 '20 at 9:52
  • A contract can only transfer from its own balance. To transfer ethers it should have been received previously or in the same transaction if the function is payable. – Ismael Feb 13 '20 at 5:38
1

First of all you transfer ethers, not money. You pass the amount you desire to transfer as Value, not as method parameter. And remember always update contract state before transfer() method, because on the example your contract is vulnerable to reentrancy attack. If transfer() method fails it will revert the state changes above. Read more here. Another problem with your contract is that your state is vulnerable to variables overflow. It's good idea to use this SafeMath contract for simple operations like addition, subtraction, multiplication and division.

pragma solidity 0.5.16;

contract SafeMath {
    /**
    * @dev Multiplies two numbers, reverts on overflow.
    */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b);

        return c;
    }

    /**
    * @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
    */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0);
        // Solidity only automatically asserts when dividing by 0
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
    * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
    */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a);
        uint256 c = a - b;

        return c;
    }

    /**
    * @dev Adds two numbers, reverts on overflow.
    */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a);

        return c;
    }

    /**
    * @dev Divides two numbers and returns the remainder (unsigned integer modulo),
    * reverts when dividing by zero.
    */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0);
        return a % b;
    }
}

contract TestContract is SafeMath {
    uint public transactionCount = 0;
    uint public transactionAmount = 0;

    function payBill(address payable account) payable public {
        transactionCount = add(transactionCount, 1);
        transactionAmount = add(transactionAmount, msg.value);

        address(account).transfer(msg.value);
    }
}
1
  • great answer. one thing to add is that starting in Solidity 0.8 SafeMath is included in normal operations implicitly, so you don't need to do explicit calls to it – WrRaThY 2 days ago

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.