0

I've combined MetaCoin and created an Ownable contract to allow for my Relay contract have access to MetaCoin methods and variables. Everything is successfully deployed using truffle. My assumption is that Relay (thereby the default account in web3.eth.accounts) should have access to methods and variables from MetaCoin. Below is the contract:

pragma solidity ^0.4.4;
import "./ConvertLib.sol";

// This is just a simple example of a coin-like contract.
// It is not standards compatible and cannot be expected to talk to other
// coin/token contracts. If you want to create a standards-compliant
// token, see: https://github.com/ConsenSys/Tokens. Cheers!

contract Ownable {
  address public owner;

  function Ownable() {
    owner = msg.sender;
  }

   modifier onlyOwner() {
    if (msg.sender != owner) {
      throw;
    }
    _;
  }

  function transferOwnership(address newOwner) onlyOwner {
    if (newOwner != address(0)) {
      owner = newOwner;
    }
  }

}

contract MetaCoin is Ownable{
    mapping (address => uint) balances;

    event Transfer(address indexed _from, address indexed _to, uint256 _value);

    function MetaCoin() {
        balances[tx.origin] = 10000;
    }

    function sendCoin(address receiver, uint amount) returns(bool sufficient) {
        if (balances[msg.sender] < amount) return false;
        balances[msg.sender] -= amount;
        balances[receiver] += amount;
        Transfer(msg.sender, receiver, amount);
        return true;
    }

    function getBalanceInEth(address addr) returns(uint){
        return ConvertLib.convert(getBalance(addr),2);
    }

    function getBalance(address addr) returns(uint) {
        return balances[addr];
    }
}

contract Relay is MetaCoin {
address public owner;
uint public count;
address[] oracles;
uint public fee;


  function Relay() {
    owner = msg.sender;
    count = 0;
    fee = 10;
  }


  function fundRelay() payable returns (bool) {
    if (owner != msg.sender) throw;

  }

function approveExternalTransaction() {
  count++;
  if (count == 3) {
    releaseFunds();
  }
}
  function releaseFunds () {

      sendCoin(owner, fee);

  }
}

I am acting as a manual oracle and I call approveExternalTransaction() 3 times, on the third time sendCoin() should be called. It currently is not being called. sendCoin() is not called when I manually call the method either.

I'm running this all successfully using truffle and I expect the pre-funded contract to release the funds to the owner (account 0 in web3.eth.accounts), but nothing is happening.

One hint is that when I call Relay.at(relay).balance() I get the error Relay.at(...).balance is not a function. Does being Ownable not inherit the balance variable declarations as well? Or is this an issue with either truffle or the way I've constructed my contracts?

Thank you for any help.


UPDATE -- Found this guide https://dappsforbeginners.wordpress.com/tutorials/interactions-between-contracts/

Changed these functions -

function approveExternalTransaction(address coinContractAddress) {
    count++;
    if (count == 3) {
      releaseFunds(coinContractAddress);
    }
  }

  function sendCoin(address coinContractAddress, address receiver, uint amount) {
        MetaCoin m = MetaCoin(coinContractAddress);
      if(m.getBalance(msg.sender) >= amount) {
        balances[msg.sender] += amount;
        balances[owner] -= amount;
      m.sendCoin(owner, fee);
    }
  }

function releaseFunds (address coinContractAddress) {
    sendCoin(coinContractAddress, owner, fee);
 }

}

The issue now is when I set address = MetaCoin.deployed().then(function(instance) { return instance.address; }) and then call Relay.at(relay).approveExternalTransaction(address) I am getting the following error:

BigNumber Error: new BigNumber() not a number: [object Object]

Any idea why this might be happening?

  • Did you mean Relay.at(relay).balances() with an 's'? Being ownable doesn't prevent inheritance of the getter function for the public mapping called balances. – Rob Hitchens - B9lab Jul 7 '17 at 20:21
  • Says TypeError: Relay.at(...).balances is not a function. When I call Relay.at(relay).sendCoin(relay, 10) I get a successful transaction but no coins get moved. – Michael O'Rourke Jul 7 '17 at 20:28
0

I've deployed your contract with remix and made 3 calls of approveExternalTransaction(). SendCoin() is successfully called, but let's see the result (event, that generated by SendCoin() function):

enter image description here

You've tried to transfer ether from owner to owner. It is seen from contract too: owner = msg.sender at deploying. Maybe this change will do, what you expect from function: sendCoin(owner, fee); -> sendCoin(msg.sender, fee);?

UPDATE

See full code:

pragma solidity ^0.4.11;

contract Ownable {
  address public owner;

  function Ownable() {
    owner = msg.sender;
  }

   modifier onlyOwner() {
    if (msg.sender != owner) {
      throw;
    }
    _;
  }

  function transferOwnership(address newOwner) onlyOwner {
    if (newOwner != address(0)) {
      owner = newOwner;
    }
  }

}

contract MetaCoin is Ownable{
    mapping (address => uint) balances;

    event Transfer(address indexed _from, address indexed _to, uint256 _value);

    function MetaCoin() {
        balances[msg.sender] = 10000;
    }

    function sendCoin(address receiver, uint amount) returns(bool sufficient) {
        if (balances[msg.sender] < amount) return false;
        balances[msg.sender] -= amount;
        balances[receiver] += amount;
        Transfer(msg.sender, receiver, amount);
        return true;
    }

    function getBalance(address addr) constant returns(uint) {
        return balances[addr];
    }
}

contract Relay is MetaCoin {
address public owner;
uint public count;
address[] oracles;
uint public fee;


  function Relay() {
    owner = msg.sender;
    count = 0;
    fee = 10;
  }


  function fundRelay() payable returns (bool) {
    if (owner != msg.sender) throw;

  }

function approveExternalTransaction(address receiver) {
    count++;
    if (count == 3) {
      releaseFunds(receiver);
    }
  }

function releaseFunds (address receiver) {
    sendCoin(receiver, fee);
 }
}
  • Thanks, I had to step out for a minute but I will check when I get home. – Michael O'Rourke Jul 7 '17 at 21:29
  • Viktor, this did not work. I also changed the parent account to acct2 - relay = Relay.new({from: acct2}).then(function(instance) { relay = instance.address;}) to avoid that and still not working. – Michael O'Rourke Jul 7 '17 at 22:48
  • @MichaelO'Rourke I've update my answer with full code: try it in Remix - it works. – Viktor Baranov Jul 8 '17 at 6:09
  • Why would it work in remix and not in the truffle console? – Michael O'Rourke Jul 8 '17 at 10:57
0

Figured it out. It was a couple issues. First with my Relay contract, I changed the names of the address variables that the functions were receiving. Because they were originally all coinContractAddress it was not playing nice with truffle. Here is what I changed them to:

  function approveExternalTransaction(address externalAddress) {
    count++;
    if (count == 3) {
      releaseFunds(externalAddress);
    }
  }

  function sendCoin(address sendAddress, address receiver, uint amount) returns(bool sufficient) {
            MetaCoin m = MetaCoin(sendAddress);
          m.sendCoin(owner, fee);
      }

function releaseFunds (address releaseAddress) {
    sendCoin(releaseAddress, owner, fee);
  }

As a result, I had no issues. The second issue was me not properly setting the MetaCoin address in truffle. I was calling:

address = MetaCoin.deployed().then(function(instance) { return instance.address; })

instead of setting the address = inside the callback

address = MetaCoin.deployed().then(function(instance) { address = instance.address; })

Everything worked perfectly after that.

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.