Best Practices für die Interaktion mit anderen Verträgen

Ich würde gerne wissen, was der beste Ansatz und die besten Praktiken sind, um mit anderen Verträgen zu interagieren.

Hier sind die MyFriendToken.solund die MyService.sol:

MyFriendToken.solIch würde gerne wissen, was der beste Ansatz und die besten Praktiken sind, um mit anderen Verträgen zu interagieren.

Hier sind die MyFriendToken.solund die 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);
            }
        }
    }
}

Hier meine Zweifel:

  1. Ist das ein guter Ansatz?
  2. Wie kann ich das Guthaben meiner Freunde verringern, nachdem sie meinen Dienst genutzt haben ( doStuff()Funktion)?

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);
            }
        }
    }
}

Hier meine Zweifel:

  1. Ist das ein guter Ansatz?
  2. Wie kann ich das Guthaben meiner Freunde verringern, nachdem sie meinen Dienst genutzt haben ( doStuff()Funktion)?

Antworten (1)

Zusamenfassend :

1-ja, Sie rufen den anderen Vertrag mit seiner Adresse auf.
2- Sie könnten in Ihrem ersten Vertrag eine Funktion erstellen wie:

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

und nennen Sie es dann in Ihrem zweiten Vertrag:

    if(myFriendBalance >= servicePrice){
mft.decrease(_value, myFriendAddress);
}
Tolle Idee! Was denken Sie stattdessen, wenn ich die Funktion tranferaufrufe? (Ich habe gerade meine Fragen geändert). Nochmals vielen Dank.
Sie könnten Transfer aufrufen, um dies gemäß Ihrem Design und Schema zu tun
Was ist in diesem Fall der Wert von msg.sender, wenn ich die Übertragungsfunktion verwende und sie aus dem MyService-Vertrag aufrufe? Die Benutzeradresse, die den Dienst nutzt, oder die Vertragsadresse, die die Funktion aufruft?
In diesem Fall ist msg.sender die Adresse des zweiten Vertrags, daher könnten Sie transferFrom verwenden und ihm die Adressen von Absender und Empfänger übergeben
Ich überlege noch, was der beste Ansatz sein könnte. Wenn ich die tranferFromaufrufe, sollte der zu übertragende Wert zunächst vom Benutzer genehmigt werden. Bedeutet das also, dass der Benutzer zuerst die approveFunktion (MyFriendToken) aufrufen und als _toArgument die Adresse des MyService-Vertrags übergeben sollte?
Da Sie möchten, dass der Anrufer ein Proxy-Vertrag und kein direkter Benutzer ist, müssen Sie meiner Meinung nach das erc20-Modell hacken. Sie könnten stattdessen die Funktion prov ändern, indem Sie msg.sender verwenden. Verwenden Sie eine Absenderadresse im fct-Parameter