Erbvertrag? Brauchen Sie Hilfe, um bestimmte Dinge zu verstehen

Ich verwende testrpc und Trüffel. Ich habe ein einfaches Token erstellt, wie es in vielen Tutorials zu sehen ist, das verwendet werden soll, um bestimmte Aktionen zu kaufen oder zu aktivieren, wenn auf eine Schaltfläche auf einer Benutzeroberfläche geklickt wird.

contract MyToken {
    mapping (address => uint) balanceOf;

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

    function MyToken() {
        balanceOf[msg.sender] = 21000000;
    }

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

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

So weit, ist es gut.

Die Benutzeroberfläche hat eine Schaltfläche „Buy 10 MyToken“, die funktioniert, da ich eine Funktion in app.js mit dem bereitgestellten JS-Objekt dieses Vertrags implementiert habe.

function buyMyToken(amount) {
  var mytoken = MyToken.deployed();

  showStatus("Initiating transaction... (please wait)");

  mytoken.sendCoin(myaccount, amount, {from: spender}).then(function() {
    showStatus("Transaction complete!");
    refreshBalance();
  }).catch(function(e) {
    console.log(e);
    showStatus("Error sending coin; see log.", true);
  });
}; 

Jetzt möchte ich einen weiteren Vertrag erstellen, der es dem Benutzer ermöglicht, eine Lizenz, einen Dienst zu kaufen oder beispielsweise eine Aktion zu aktivieren, wenn er auf eine andere Schaltfläche klickt. In diesem Fall soll ein Bild dauerhaft auf der Benutzeroberfläche aktiviert werden, wenn es einmal mit diesem Token gekauft wird. Diese zweite Schaltfläche sollte also ein Gimmick dauerhaft aktivieren und die Kosten betragen beispielsweise 5 meiner selbst erstellten Token --> "Gimmick aktivieren (5 MyToken)"

Dafür ist eine Vertragsvererbung erforderlich, oder? Weil der zweite Vertrag prüfen muss, ob der Benutzer bereits einige der Token mit dem ersten Vertrag gekauft hat, was ihm erlauben würde, eine Lizenz, einen Dienst zu kaufen oder eine Aktion mit dem zweiten Vertrag zu ermöglichen. Was brauche ich also für diesen zweiten Vertrag und wie kann ich ihn in Verbindung mit dem ersten Vertrag erstellen und verwenden?

Könnte der zweite Vertrag so sein oder was brauche ich noch? Ich weiß, dass ich zum Beispiel die getBalance-Funktion vom ersten Vertrag brauche, oder? Aber wie und wo setze ich sie ein?

contract PermService {
  address vendor;

  event ServiceTransfer(address _from, address _to, uint _amount)

  function PermService() {
  vendor = msg.sender;


  }

  function buyPermService() returns (bool success) {
  if...
  ...
  ServiceTransfer(msg.sender, receiver, amount);
  return true;
  }
}

Macht das überhaupt Sinn?

Kann nicht wirklich gute Tutorials für Nebenwährungen finden und wie man sie mit anderen Verträgen verwendet. Ich bin auch ein Noob und kein Pro-Coder.

Und kann ich das mit Truffle Console simulieren?

Hilfe wird sehr geschätzt. Vielen Dank im Voraus.

Antworten (3)

Ok das habe ich bisher gemacht. Und ja, es ist nicht die Vertragsvererbung, wonach ich gesucht habe, es sind Verträge, die miteinander interagieren.

contract MyToken {
    mapping (address => uint) balanceOf;

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

    function MyToken() {
        balanceOf[msg.sender] = 21000000;
    }

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

    function transfer(address from, address to, uint amount) returns(bool sufficient) {
        if (balanceOf[from] < amount) return false;
        balanceOf[from] -= amount;
        balanceOf[to] += amount;
        CoinTransfer(from, to, amount);
        return true;
    }

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

contract PermService {
    mapping (address => bool) customerPaid;
    address vendor;

    function PermService() {
        vendor = msg.sender;
    }

    function buy(address tokenContractAddress) returns (bool success) {
        if (customerPaid[msg.sender]) {
            // permanent: the customer already bought the service!
            return true;
        }
        MyToken mt = MyToken(tokenContractAddress);
        if (mt.getBalance(msg.sender) < 5) {
            throw;
            return false;
        }
        mt.transfer(msg.sender, vendor, 5);
        customerPaid[msg.sender] = true;
        return true;
    }
}

contract OnetimeService {
    address vendor;

    function OnetimeService() {
        vendor = msg.sender;
    }

    function buy(address tokenContractAddress) returns (bool success) {
        MyToken mt = MyToken(tokenContractAddress);
        if (mt.getBalance(msg.sender) < 2) {
            return false;
        }
        mt.sendCoin(vendor, 2);

        return true;
    }

}

contract TimeLimitedService {
     ....
     //block.timestamp an option??

}

Wie Sie sehen können, habe ich 4 Verträge in einer Datei erstellt. 4 Schaltflächen in der Benutzeroberfläche und für jeden habe ich einen Vertrag erstellt. Der erste Vertrag erstellt das Token, das von Kunden verwendet werden kann, um Dienstleistungen vom Aussteller dieses Tokens zu kaufen. Wie ich in meinem Eröffnungskommentar erwähnt habe, funktioniert dies bereits. Der Kunde klickt auf die Schaltfläche „10 Mytoken kaufen“ und fertig.

Der zweite Vertrag soll eine dauerhafte Leistung ermöglichen, die nur einmal gekauft werden muss. Bisher funktioniert dies meistens. Wenn ich kein MyToken gekauft habe und auf die Schaltfläche "Gimmick aktivieren" drücke, wird "Fehler beim Kauf des Dienstes, siehe Protokoll" zurückgegeben. Das ist richtig. Und wenn ich zuerst etwas von MyToken kaufe und dann auf „Gimmick aktivieren“ drücke, erscheint ein Gimmick und das Guthaben wird um 5 MyToken reduziert vorher gekauft. Es finden jedoch immer noch Transaktionen statt. Nicht die perfekte Lösung, die ich bisher habe. Ich bin mir sicher, dass es viel bessere Möglichkeiten gibt, das zu codieren. Verbesserungen und Vereinfachungen sind willkommen.

Und eine Idee, wie ich einen Smart Contract mit einer zeitlich begrenzten Dienstleistung/Aktion schreiben kann? Ich habe gelesen, dass block.timestampdies eine Option sein könnte. Die Idee ist, dass, wenn von diesem Moment an eine Schaltfläche in der Benutzeroberfläche gedrückt wird oder wenn diese Transaktion in einen Block aufgenommen wurde, sich die Farbe des Hintergrunds für 30 Sekunden oder so ähnlich ändern kann .Einige Hilfe hier wird ebenfalls geschätzt.

Möglicherweise suchen Sie hier nicht nach Vertragserbschaft.

Wenn Vertrag B von Vertrag A erbt, ist es (im Allgemeinen) eine vollständige Kopie von A sowie was auch immer B hinzufügt. Wenn Sie also einen Token-Vertrag erstellen und dann einen zweiten Vertrag erstellen, der vom Token-Vertrag erbt, haben Sie tatsächlich zwei Arten von Token!

Dies ist jedoch möglicherweise keine schlechte Sache. Wenn der Verkauf dieser Dienstleistung untrennbar mit dem Token verbunden ist, könnte es sinnvoller sein, nur einen Vertrag zu haben, der sowohl die Token verfolgt als auch Dienstleistungen verkauft. Es gibt jedoch eine Reihe von Gründen, warum Sie dies möglicherweise nicht tun möchten. (Komplexität, Schwierigkeit beim Upgrade usw.)

Wie macht man das mit zwei Verträgen? Im Wesentlichen müssen Sie dem Verkäufervertrag das Recht einräumen, das Gleichgewicht des Token-Vertrags zu ändern. Hier ist ein Ausschnitt für eine einfache Möglichkeit, dies zu tun.

modifer onlyseller() {
    if(msg.sender != seller) throw;
    _;
}

function takeTokens(address buyer, uint amount) onlyseller {
    if(balanceOf[buyer] < amount) throw;
    balanceOf[buyer] -= amount;
    balanceOf[seller] += amount;
    CoinTransfer(msg.sender, receiver, amount);
}

Dadurch wird eine Funktion im Token-Vertrag erstellt, auf die nur zugegriffen werden sellerkann. Jeder andere Anruf wird throw. (In diesem Fall ist das wahrscheinlich eine gute Sache. throwMacht (im Allgemeinen) die gesamte Transaktion rückgängig.)

Dann können Sie im Verkäufervertrag diese Funktion nutzen.

// in the constructor.
mytoken = MyToken(tokenContractAddress);

// in buyPermService(). I assume msg.sender is the buyer.
// you'll need to mark balanceOf as public for this to work.
if(mytoken.balanceOf(msg.sender) > priceOfService) { 
    mytoken.takeTokens(msg.sender, priceOfService);
    // Actually provide the service here.
}  

Dies ist jedoch nicht die beste Methode.

Der ERC20-Token-Standard (eine großartige Ressource zu Token im Allgemeinen) spezifiziert eine Methode namens transferFrom()und empfiehlt eine Methode namens approve(). Eine Adresse kann verwendet approve()werden, um einer anderen Adresse zu erlauben, einige Token durch abzuheben transferFrom(). Damit wäre es einfach, einen Verkäufervertrag zu erstellen. Der Käufer gibt dem Verkäufer das Recht, so viele Token durch abzuheben approve(), und der Verkäufer verwendet transferFrom(), um diese Token tatsächlich zu erhalten. Dies ist in der Tat viel besser, da Sie (oder jeder andere) neue Verkäufer zum System hinzufügen können. Es wäre Ihre Zeit wert, dies zu implementieren.

Danke für deine Antwort. Muss später deine Empfehlungen durchgehen. Ich habe ein bisschen mit meiner eigenen Version herumgespielt. Werde sie auch hier posten und vielleicht kannst du sie dir für einige Verbesserungen ansehen.

Stimmen Sie Mathew über ERC20 im Vergleich zu Roll-your-own-Token zu. Ich bin mir nicht sicher, ob zeitlich begrenzt wirklich das ist, was Sie für einen OneTimeService wollen. Hier ist eine andere Möglichkeit, auf jeden Fall ein Timing zu sehen:

 function f(uint durationInMinutes) {
    uint deadline = now + durationInMinutes * 1 minutes;
 } // unit time in seconds +/- 900 seconds

Ich bin mir nicht sicher, ob Sie einen separaten Vertrag für den oneTimeService benötigen ... Ich bin mir nicht sicher, ob das Timing der richtige Weg ist. Erwägen Sie, es explizit einmalig zu machen, wenn dies die Absicht ist:

contract C {

mapping(address => bool) alreadyDone;

function oneTime(address user) returns(bool success) {
    if(alreadyDone[user]) throw;
    // do something
    alreadyDone[user]=true;
}

}

Wenn dies für die Benutzeroberfläche dient, möchten Sie wahrscheinlich das einmalige Muster und einen Ereignisemitter oder eine abgebaute Transaktion verwenden, um zu bestätigen, dass etwas wirklich passiert ist.

hinzufügen:

event LogItHappened(address user); // initialize it

//do something
LogItHappened(user); // UI can watch for this with an event listener.