3

The title of this issue might seem strange because I can't figure out exactly what the problem is. But here is what is happening:

pragma solidity ^0.4.13;

contract Escrow {
  address public owner;
  uint public fee;

  //Balances temporarily made public for testing; to be removed
  mapping (address =>  mapping (address => uint)) public balances;

  function Escrow() public {
    owner = msg.sender;
  }

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

  //Fee should be set in PPM
  function setFee(uint price) onlyOwner external {
    fee = price;
  }

  function start(address payee) payable external {
    balances[msg.sender][payee] = balances[msg.sender][payee] + msg.value;
  }

  function end(address payer, address payee) onlyOwner external {
    uint value = balances[payer][payee];
    //uint paidFee = value / (1000000 / fee);
    //uint payment = value - paidFee;
    //payee.transfer(payment);
    //owner.transfer(paidFee);
    //balances[payer][payee] = 0
    payee.transfer(value)
  }
}

I've commented out a bunch of lines that I would like to get working in the end function, because I can't get even the other parts working.

Steps:

  1. Creat contract from first address in testRPC

  2. I call start, from the second address in my testRPC, sending 2 ETH, to the last address: start("0xb631fc401038e191fa38c4ff20dcce8d13eb6ebc" , { from "0x1c34d277b51ec49536fe7843e289933e0f8020ed", value: 2000000000000000000000 })

  3. I check: balances("0x1c34d277b51ec49536fe7843e289933e0f8020ed", "0xb631fc401038e191fa38c4ff20dcce8d13eb6ebc"), I see 0: uint256: 2000000000000000000 --So far so good.

  4. This is where I get into trouble. If I call end("0x1c34d277b51ec49536fe7843e289933e0f8020ed", "0xb631fc401038e191fa38c4ff20dcce8d13eb6ebc"), I get: transact to Escrow.end errored: VM Exception while processing transaction: out of gas

If I change end to just return balances[payer][payee], I get 0.

If I change end to just transfer 1 ETH to payee, I get a gas error.

So I can't figure out what the source of this issue is. Can you give any advice?

  • Superficially, it appears to work as expected, so I imagine the issue might be outside the code. Can you elaborate on step 1? How exactly do you go about "Creat contract from first address in testRPC"? Are you copying bytecode from Remix, deploying using Remix, compiling/deploying with truffle or something else? There is some ambiguity with pragma ^0.4.13 and your process. I suspect you've got version incompatibilities to sort out. A suggestion is to remove the ^ and resolve the resulting complaints by bringing things into strong explicit alignment. Hope it helps. – Rob Hitchens Jun 28 '18 at 3:35
1

end() method of this contract should be payable as there is transfer inside the method. And also use safeMath.sol of OpenZeppelin for any mathematical calculation inside contract. I rewrite the code. Please find:

safeMath.sol

pragma solidity ^0.4.21;

/**
 * @author OpenZeppelin
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
library SafeMath {
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a * b;
        assert(a == 0 || c / a == b);
        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // assert(b > 0); // Solidity automatically throws 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;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        assert(b <= a);
        return a - b;
    }

    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        assert(c >= a);
        return c;
    }
}

escrow.sol

pragma solidity ^0.4.21;

import './safeMath.sol';

contract Escrow {

    using SafeMath for uint;

    address public owner;
    uint public fee;

    mapping (address =>  mapping (address => uint)) public balances;

    function Escrow() public {
        owner = msg.sender;
    }

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

    //Fee should be set in PPM
    function setFee(uint price) onlyOwner external {
        fee = price;
    }

    function start(address payee) payable external {
        balances[msg.sender][payee] = balances[msg.sender][payee] + msg.value;
    }

    function end(address payer, address payee) onlyOwner payable external {
        uint value = balances[payer][payee];
        uint paidFee = value.div(uint(1000000).div(fee));
        uint payment = value.sub(paidFee);
        payee.transfer(payment);
        owner.transfer(paidFee);
        balances[payer][payee] = 0;
        payee.transfer(value);
    }
}
0

The code you pasted here works fine, except the forgotton ; at payee.transfer(value).

My guess is that as the error says, you simply didn't provide enough gas.

enter image description here

  • How were you able to set a gas amount in Remix? – Jon Sanders Apr 23 '18 at 23:02
  • BTW, I'm using Ganache as my test RPC, so the environment is Web3 provider – Jon Sanders Apr 23 '18 at 23:20
  • Top-right. "Gas limit" and "wei" (which can you change to ether) allow you to "configure" your tx. – Eli Drion Apr 24 '18 at 8:51
  • I know that I can raise the gas limit, which I've done. You are saying that I should also put some eth into the value form? – Jon Sanders Apr 24 '18 at 13:27
0

I think you need to add the from account in step 4, like you have in step 2 but without any value. Otherwise it doesn't know what account to charge for gas.

  • Thanks for the idea. I am doing this from the Remix IDE, so a From value is required, and I've been doing it from the owner. – Jon Sanders Apr 23 '18 at 22:57
  • It executed for me with the JavaScript VM. Have you tested other environments? Screenshot: imgur.com/a/Gf0fjqu – sfmiller940 Apr 24 '18 at 4:59
  • Goodness. I banged my head on this for so long, and it seems to be an issue with my testRPC. It works just fine from the Javascript VM. Do you have any idea why this might be? – Jon Sanders Apr 24 '18 at 13:26
  • Try googling "ethereum testrpc out of gas". There are several posts with a similar issue. – sfmiller940 Apr 24 '18 at 16:56
0

From your code

function start(address payee) payable external {
    balances[msg.sender][payee] = balances[msg.sender][payee] + msg.value;
  }

To call this function ,

start("0xb631fc401038e191fa38c4ff20dcce8d13eb6ebc" , { from "0x1c34d277b51ec49536fe7843e289933e0f8020ed", value: 2000000000000000000000 })

You passed Value and now your value is stored on balances[msg.sender][payee] finally after adding.
Lets jump on second function

function end(address payer, address payee) onlyOwner external {
    uint value = balances[payer][payee];
     payee.transfer(value);  
  }

for the first time you transact this function then all your value is transferred to an address of payee.
for the second time you transact this function then you have no value left then you get the vm error.

If you have not did this mistake then check web3js. please pass optional parameter.

end("0x1c34d277b51ec49536fe7843e289933e0f8020ed", "0xb631fc401038e191fa38c4ff20dcce8d13eb6ebc",{from,gasPrice,gas})

options - Object (optional): The options used for calling.
        from - String (optional): The address the call “transaction” should be made from.
        gasPrice - String (optional): The gas price in wei to use for this call “transaction”.
        gas - Number (optional): The maximum gas provided for this call “transaction” (gas limit).

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.