Wie man eine bessere Demokratie in weniger als 100 Codezeilen aufbaut [geschlossen]

Hallo Freunde, nach drei Tagen Recherche und viel Hilfe der Community habe ich mein Problem mit dem Code of Democracy Smart Contract nach diesem Tutorial gelöst: https://blog.ethereum.org/2015/12/04/ethereum-in-practice -teil-2-wie-man-eine-bessere-demokratie-in-unter-100-zeilen-code-aufbaut/

Ich habe den Absturz mit dem Namen "Rückgabewert von nicht verwendeten Low-Level-Aufrufen": Rückgabewert von nicht verwendeten Low-Level-Aufrufen

Also löse ich das Problem mit Rob Hitchens Rat und mache meinen Code so

pragma solidity 0.4.8;
contract token { mapping (address => uint256) public balanceOf; }

/* The democracy contract itself */
contract Democracy {

    /* Contract Variables and events */
    uint public minimumQuorum;
    uint public debatingPeriodInMinutes;
    Proposal[] public proposals;
    uint public numProposals;
    token public sharesTokenAddress;

    event ProposalAdded(uint proposalID, address recipient, uint amount, string description);
    event Voted(uint proposalID, bool position, address voter);
    event ProposalTallied(uint proposalID, int result, uint quorum, bool active);

    struct Proposal {
        address recipient;
        uint amount;
        string description;
        uint votingDeadline;
        bool openToVote;
        bool proposalPassed;
        uint numberOfVotes;
        bytes32 proposalHash;
        Vote[] votes;
        mapping (address => bool) voted;
    }

    struct Vote {
        bool inSupport;
        address voter;
    }

    /* modifier that allows only shareholders to vote and create new proposals */
    modifier onlyShareholders {
        if (sharesTokenAddress.balanceOf(msg.sender) == 0) throw;
        _;
    }

    /* First time setup */
    function Democracy(token sharesAddress, uint minimumSharesForVoting, uint minutesForDebate) {
        sharesTokenAddress = token(sharesAddress);
        if (minimumSharesForVoting == 0 ) minimumSharesForVoting = 1;
        minimumQuorum = minimumSharesForVoting;
        debatingPeriodInMinutes = minutesForDebate;
    }

    /* Function to create a new proposal */
    function newProposal(address beneficiary, uint etherAmount, string JobDescription, bytes transactionBytecode) onlyShareholders returns (uint proposalID) {
        proposalID = proposals.length++;
        Proposal p = proposals[proposalID];
        p.recipient = beneficiary;
        p.amount = etherAmount;
        p.description = JobDescription;
        p.proposalHash = sha3(beneficiary, etherAmount, transactionBytecode);
        p.votingDeadline = now + debatingPeriodInMinutes * 1 minutes;
        p.openToVote = true;
        p.proposalPassed = false;
        p.numberOfVotes = 0;
        ProposalAdded(proposalID, beneficiary, etherAmount, JobDescription);
        numProposals = proposalID+1;
    }

    /* function to check if a proposal code matches */
    function checkProposalCode(uint proposalNumber, address beneficiary, uint etherAmount, bytes transactionBytecode) constant returns (bool codeChecksOut) {
        Proposal p = proposals[proposalNumber];
        return p.proposalHash == sha3(beneficiary, etherAmount, transactionBytecode);
    }

    /* */
    function vote(uint proposalNumber, bool supportsProposal) onlyShareholders returns (uint voteID){
        Proposal p = proposals[proposalNumber];
        if (p.voted[msg.sender] == true) throw;

        voteID = p.votes.length++;
        p.votes[voteID] = Vote({inSupport: supportsProposal, voter: msg.sender});
        p.voted[msg.sender] = true;
        p.numberOfVotes = voteID +1;
        Voted(proposalNumber,  supportsProposal, msg.sender);
    }

    function executeProposal(uint proposalNumber, bytes transactionBytecode) returns (int result) {
        Proposal p = proposals[proposalNumber];
        /* Check if the proposal can be executed */
        if (now < p.votingDeadline  /* has the voting deadline arrived? */
            || !p.openToVote        /* has it been already executed? */
            ||  p.proposalHash != sha3(p.recipient, p.amount, transactionBytecode)) /* Does the transaction code match the proposal? */
            throw;

        /* tally the votes */
        uint quorum = 0;
        uint yea = 0;
        uint nay = 0;

        for (uint i = 0; i <  p.votes.length; ++i) {
            Vote v = p.votes[i];
            uint voteWeight = sharesTokenAddress.balanceOf(v.voter);
            quorum += voteWeight;
            if (v.inSupport) {
                yea += voteWeight;
            } else {
                nay += voteWeight;
            }
        }
        /* execute result */
        if (quorum > minimumQuorum && yea > nay ) {
            // has quorum and was approved
            if(p.recipient.call.value(p.amount*1000000000000000000)(transactionBytecode)) {
        // do something
         p.openToVote = false;
    } else {
        // do something else
         p.proposalPassed = true;
    }
        } else if (quorum > minimumQuorum && nay > yea) {
            p.openToVote = false;
            p.proposalPassed = false;
        }
        /* Fire Events */
        ProposalTallied(proposalNumber, result, quorum, p.openToVote);
    }
}

das System akzeptiert es also. Ich möchte fragen, ob der Code für die Bereitstellung des Vertrags geeignet ist oder ob ich hier einen Fehler mache

Geben Sie hier die Bildbeschreibung ein

Vielen Dank im Voraus!

Ich denke, Sie müssen sich fragen: "Macht der Code, was ich will?" Um diese Frage zu beantworten, müssen Sie sie testen, und um sie richtig zu testen, müssen Sie vollständig verstehen, was der Code tut. Dieser Vorgang wird Ihnen sehr dabei helfen, zu verstehen, wie Solidity und Smart Contracts funktionieren :-)

Antworten (1)

Achtung bzgl.:

gut für die Bereitstellung des Vertrags oder ich mache hier einen Fehler

Ich vermute, es ist unrealistisch, Benutzer in diesem Forum zu bitten, zu bestätigen, dass der Code fehlerfrei ist. Ich sehe scheinbare Abweichungen von Best Practices und Problembereichen. Also noch nicht .

Ich stimme Richard darin zu, dass die Verfolgung der unten angesprochenen Punkte Ihrem Verständnis sehr helfen wird.

Ich habe meine Antwort unter Rückgabewert von Low-Level-Aufrufen nicht verwendet ausgearbeitet . Beantwortete die ursprüngliche Frage (ungefähr, warum beschwert sich der Compiler?) und gab ein wenig mehr Anleitung zu // do something // do something else. Zusammenfassend lässt sich sagen, seien Sie vorsichtig und beachten Sie die hier beschriebenen Best Practices: https://github.com/ConsenSys/smart-contract-best-practices

Unter der Überschrift „ Externe Anrufe “ finden Sie ein Muster mit der Bezeichnung „Schlecht“ und es scheint mit Ihrem Code übereinzustimmen.

Der Wiedereintritt ist also ein Problem, da ich nach dem externen Aufruf eine Manipulation der Zustandsvariablen sehe.

Ein weiteres Problem ist das Vorhandensein einer forSchleife.

for (uint i = 0; i <  p.votes.length; ++i) {

Während dies möglicherweise an anderer Stelle im Code gemildert wird, ist es zumindest für mich nicht offensichtlich. Ich sehe nichts, was einschränkt p.votes.length. Das würde bedeuten, dass die Anzahl der Iterationen über die Schleife nicht begrenzt ist. Das würde dazu führen, dass eine Funktion aufgrund des BlockgasLimits über eine bestimmte Anzahl von Stimmen ihre Aufgabe nicht erfüllen kann. Sollen wir verstehen, dass, wenn der Vertrag erfolgreich ist und es viele Wähler gibt, der Vertrag brechen soll? Offensichtlich nein, also müsste ich verstehen, warum das nicht passieren wird, bevor ich mich damit wohlfühlen könnte.

Ein weiteres Problem ist die (kluge?) Verwendung von transactionByteCode. Es scheint viel Flexibilität zu bieten; möglicherweise zu viel Flexibilität. Es scheint die Angriffsfläche und die Testfälle zu vergrößern. Mit diesem Schritt wechseln die Dinge von einer endlichen Liste von Dingen, die der Vertrag tut, zu einer möglicherweise unbegrenzten Liste von Dingen, die der ByteCode tun könnte.

Das Problem bei solchen Dingen besteht darin, vorherzusehen, wie sie in der Testphase verwendet und missbraucht werden könnten und wie Schwachstellen möglicherweise erst auftauchen, wenn dem Vertrag ein erheblicher Wert anvertraut wird und Angreifer motiviert sind, eine Schwachstelle zu finden. Kurz gesagt, es gibt einen himmelweiten Unterschied zwischen der Frage hier in SE und dem Setzen einer Million Dollar Prämie auf die Frage. Die Beweislast würde ich den Befürwortern der Strategie auferlegen. Machen Sie sich keine Sorgen darüber, zu beweisen, dass es einen Weg gibt, es zu hacken. Jemand muss beweisen, dass es keine Möglichkeit gibt , es zu hacken.

Ich sehe jetzt, dass Sie einem Tutorial folgen. Eine gelegentliche Überprüfung legt nahe, dass der Beitrag seit 2015 nicht mehr aktualisiert wurde , lange vor dem DAO-Hack 2016. Außerdem wurde es nicht aktualisiert, um das Compiler-Problem zu beheben, das zuerst in Ihrem anderen Beitrag gemeldet wurde. Diese Beobachtungen raten zur Vorsicht bei der Verwendung dieses Beispiels.

In Anbetracht der Quelle ist es möglich, dass sich andere die Zeit genommen haben, wirklich zu verstehen, was der Vertrag bei jedem Schritt des Weges tut. Es ist möglich, dass alle meine drei Bedenken beiseite geschoben werden können, wenn sich jemand mit einer zufriedenstellenden Erklärung dazu meldet, wie defensiv der Vertrag ist.

Ich stimme Richard zu. Sie sollten immer wissen, was Ihr Vertrag tut. Sie können nicht vorsichtig genug mit einer Software sein, die nicht modifiziert werden kann. Ich habe drei Bedenken mit nur einem flüchtigen Blick auf den Code gefunden, daher fühle ich mich alles andere als wohl dabei, meine Zuversicht auszudrücken, dass alles bereit ist.

Es könnte besser sein, das Beispiel als Demonstration des Potenzials von Ethereum zu betrachten, aber nicht als kampfbereite Lösung für die reale Welt.

Ich hoffe es hilft.