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)?
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);
}
  • 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 0:12
  • you could call transfer is apt to you to do so according to your design and schema – Badr Bellaj Jul 12 '17 at 0: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 0: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 0: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

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.