3

I would like to know what is the best approach and the best practices to intercat with other contracts.

Here are the MyFriendToken.sol and the MyService.sol:

MyFriendToken.sol I would like to know what is the best approach and the best practices to intercat with other contracts.

Here are the MyFriendToken.sol and the MyService.sol:

MyFriendToken.sol

pragma solidity ^0.4.0;
contract ERC20 {
    //here are the same function in the TokenContractFragment
    //https://theethereum.wiki/w/index.php/ERC20_Token_Standard

    function allowance(address _owner, address _spender) constant returns (uint remaining);
    event Transfer(address indexed _from, address indexed _to, uint _value);
    event Approval(address indexed _owner, address indexed _spender, uint _value);


    function approve(address _spender, uint256 _amount) returns (bool success) {
        if ((_amount != 0) && (allowed[msg.sender][_spender] != 0)) {
            return false;
        }
        allowed[msg.sender][_spender] = _amount;
        Approval(msg.sender, _spender, _amount);
        return true;
    }

    function transfer(address _to, uint256 _amount) onlyPayloadSize(2 * 32) returns (bool success) {
        if (balances[msg.sender] >= _amount && _amount > 0 && balances[_to] + _amount > balances[_to]) {
            balances[msg.sender] -= _amount;
            balances[_to] += _amount;
            Transfer(msg.sender, _to, _amount);
            return true;
        } else {
            return false;
        }
    }

    function transferFrom(address _from, address _to, uint256 _amount)
    returns (bool success) {
        if (
        balances[_from] >= _amount
        && allowed[_from][msg.sender] >= _amount //the transfer is approved
        && _amount > 0
        && balances[_to] + _amount > balances[_to]) {
            balances[_from] -= _amount;
            allowed[_from][msg.sender] -= _amount;
            balances[_to] += _amount;
            Transfer(_from, _to, _amount);
            return true;
        } else {
            return false;
        }
    }

    uint public totalSupply = 0;
    mapping(address => uint256) balances;
    mapping(address => mapping (address => uint256)) allowed;

    function balanceOf(address _owner) constant returns (uint balance){
        return balances[_owner];
    }
}

contract MyFriendToken is ERC20{
    string public token_name;
    string public symbol;
    uint8 public decimals;

    address public owner;

    bool purchase_OK = true;

    address friend1 = address(0x112233...);
    address friend2 = address(0x112222...);

    //.....

    function isMyFriend(address myFriendAddress) returns (bool){
        if(myFriendAddress != friend1 && myFriendAddress != friend2) {
            return false;
        }
        return true;
    }


    function purchase_ko() {
        if(msg.sender != owner){ throw;}
        purchase_OK = false;
    }

    function purchase_ok()  {
        if(msg.sender != owner){ throw;}
        purchase_OK = true;
    }

    function MyFriendToken(){
        owner = msg.sender;
        token_name = "MyFriendToken";
        symbol = "MFT";
        decimals = 18;
    }


    function kill() {
        if (msg.sender == owner) {
            selfdestruct(owner);
        }
    }

    function() payable {
        if(!purchase_OK){throw;}
        if(!isMyFriend(msg.sender)) {throw;}

        owner.transfer(msg.value);
        uint256 MyFriendToken = (msg.value * 1000);
        totalSupply += MyFriendToken;
        balances[msg.sender] += MyFriendToken;
    }
}

MyService.sol

pragma solidity ^0.4.0;

//interface to MyFriendToken
contract MyFriendToken{
    function isMyFriend(address myFriendAddress) returns (bool);
    function transferFrom(address _from, address _to, uint _value) returns (bool success);
    function approve(address _spender, uint _value) returns (bool success);
    function balanceOf(address _owner) constant returns (uint balance);
}

contract MyService {
    address public owner;

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


    event DoStuff(address myFriendAddress, uint myFriendBalance);

    function doStuff(address myFriendTokenContractAddress){
        address myFriendAddress = msg.sender;
        MyFriendToken mft = MyFriendToken(myFriendTokenContractAddress);

        if(mft.isMyFriend(myFriendAddress)){
            //check my friend's balance
            uint myFriendBalance = mft.balanceOf(myFriendAddress);

            //the price of the service is 10 MFT
            uint servicePrice = 10;

            if(myFriendBalance >= servicePrice){
                //decrese myFriend Balance

                //do stuff
                DoStuff(myFriendAddress , myFriendBalance);
            }
        }
    }
}

Here are my doubts:

  1. Is this a good approach?
  2. How can I decrease my friends' balance after they used my service (doStuff() function)?

MyService.sol

pragma solidity ^0.4.0;

//interface to MyFriendToken
contract MyFriendToken{
    function isMyFriend(address myFriendAddress) returns (bool);
    function transferFrom(address _from, address _to, uint _value) returns (bool success);
    function approve(address _spender, uint _value) returns (bool success);
    function balanceOf(address _owner) constant returns (uint balance);
    function transfer(address _to, uint _value) returns (bool success);

}

contract MyService {
    address public owner;

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


    event DoStuff(address myFriendAddress, uint myFriendBalance);

    function doStuff(address myFriendTokenContractAddress){
        address myFriendAddress = msg.sender;
        MyFriendToken mft = MyFriendToken(myFriendTokenContractAddress);

        if(mft.isMyFriend(myFriendAddress)){
            //check my friend's balance
            uint myFriendBalance = mft.balanceOf(myFriendAddress);

            //the price of the service is 10 MFT
            uint servicePrice = 10;

            if(myFriendBalance >= servicePrice){
                //decrese myFriend Balance
                transfer(owner, servicePrice);
                //do stuff
                DoStuff(myFriendAddress , myFriendBalance);
            }
        }
    }
}

Here are my doubts:

  1. Is this a good approach?
  2. How can I decrease my friends' balance after they used my service (doStuff() function)?
d3llafr33
  • 619
  • 5
  • 14

1 Answers1

1

in short :

1-yes you call the other contract using its address.
2- you could creat a function in your first contract like :

function decrease(uint256 _value, address user){
            balances[user] -= _value;
}

and then call it in your second contract :

    if(myFriendBalance >= servicePrice){
mft.decrease(_value, myFriendAddress);
}
Badr Bellaj
  • 18,780
  • 4
  • 58
  • 75
  • Greta idea! Instead, what do you think if I call the function tranfer? (I've just modified my questions). Again, many thanks. – d3llafr33 Jul 12 '17 at 00:12
  • you could call transfer is apt to you to do so according to your design and schema – Badr Bellaj Jul 12 '17 at 00:15
  • in this case, if I use the transfer function and I call it from MyService contract, what is the value of msg.sender? The user address that use the service, or the contract address that call the function? – d3llafr33 Jul 12 '17 at 00:19
  • in this case msg.sender will be the second contract's address therfore you could use transferFrom and pass to it the addresses of sender and receiver – Badr Bellaj Jul 12 '17 at 00:28
  • I'm still thinking about what could be the best approach. If I call the tranferFrom, the value to be tranferred should be first approved by the user. So does it mean the user should first call the approve function (MyFriendToken), passing as _to argument the address of MyService contract? – d3llafr33 Jul 12 '17 at 12:38
  • as you want that the caller will be a proxy contract not a direct user i think you need to hack the erc20 model . you could change the prov function instead using msg.sender use a sender's address in the fct parameter – Badr Bellaj Jul 12 '17 at 12:40