2

So i'm having some trouble with this. Basically i'm trying to initiate a contract that sends MetaCoins to an address. The other contract is supposed to subtract from the balance of MetaCoin to pay for the OtherCoin. The balances of OtherCoin are accurate, but it's not firing m.sendCoin.

The owner of the OtherCoin contract should be receiving MetaCoin from the purchaser...

pragma solidity ^0.4.2;

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 MetaCoin {
    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 getBalanceInEth(address addr) returns(uint){
        return ConvertLib.convert(getBalance(addr),2);
    }

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

contract otherCoin {
  mapping (address => uint) balances;
  address owner;

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

  function purchaseCoin(address coinContractAddress, uint amount) returns(bool sufficient) {
    MetaCoin m = MetaCoin(coinContractAddress);
    if(m.getBalance(msg.sender) >= amount) {
      balances[msg.sender] += amount;
      balances[owner] -= amount;
      m.sendCoin(owner, amount);
      return true;
    }
    throw;
  }

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

What am I missing here?

4

When you call m.sendCoin() in otherCoin, the msg.sender of that call isn't the purchaser, it's the otherCoin contract itself. That means your contract is trying to send its owner its own MetaCoins, when you want it to send the purchaser's.

It should do what you expect if you change MetaCoin so that it uses tx.origin instead of msg.sender. In the simple case this will be the purchaser.

However, using tx.origin is generally considered bad practice, because it breaks the ability for contracts to control funds. The design to send funds on someone's behalf used in the standard for token contracts, ERC20, is to first have them approve() transfer by the contract up to a certain limit, then to call transferFrom() (instead of the normal transfer() which is the ERC20 equivalent of MetaCoin's sendCoin). This allows the calling contract to specify whose funds should be moved.

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.