Der Wert kann nicht von der Zuordnung innerhalb der Zuordnung übertragen werden

Der Titel dieser Ausgabe mag seltsam erscheinen, weil ich nicht genau herausfinden kann, was das Problem ist. Aber hier ist, was passiert:

pragma solidity ^0.4.13;

contract Escrow {
  address public owner;
  uint public fee;

  //Balances temporarily made public for testing; to be removed
  mapping (address =>  mapping (address => uint)) public balances;

  function Escrow() public {
    owner = msg.sender;
  }

  modifier onlyOwner() {
    require(msg.sender == owner);
    _;
  }

  //Fee should be set in PPM
  function setFee(uint price) onlyOwner external {
    fee = price;
  }

  function start(address payee) payable external {
    balances[msg.sender][payee] = balances[msg.sender][payee] + msg.value;
  }

  function end(address payer, address payee) onlyOwner external {
    uint value = balances[payer][payee];
    //uint paidFee = value / (1000000 / fee);
    //uint payment = value - paidFee;
    //payee.transfer(payment);
    //owner.transfer(paidFee);
    //balances[payer][payee] = 0
    payee.transfer(value)
  }
}

Ich habe eine Reihe von Zeilen auskommentiert, die ich gerne in der endFunktion zum Laufen bringen würde, weil ich nicht einmal die anderen Teile zum Laufen bringen kann.

Schritte:

  1. Vertrag von erster Adresse in testRPC erstellen

  2. Ich rufe start von der zweiten Adresse in meinem testRPC an und sende 2 ETH an die letzte Adresse:start("0xb631fc401038e191fa38c4ff20dcce8d13eb6ebc" , { from "0x1c34d277b51ec49536fe7843e289933e0f8020ed", value: 2000000000000000000000 })

  3. Ich überprüfe: balances("0x1c34d277b51ec49536fe7843e289933e0f8020ed", "0xb631fc401038e191fa38c4ff20dcce8d13eb6ebc"), ich sehe 0: uint256: 2000000000000000000--So weit, so gut.

  4. Hier komme ich in Schwierigkeiten. Wenn ich anrufe end("0x1c34d277b51ec49536fe7843e289933e0f8020ed", "0xb631fc401038e191fa38c4ff20dcce8d13eb6ebc"), bekomme ich:transact to Escrow.end errored: VM Exception while processing transaction: out of gas

Wenn ich endzu just return ändere balances[payer][payee], bekomme ich 0.

Wenn ich ändere end, um nur 1 ETH an den Zahlungsempfänger zu überweisen, erhalte ich einen Gasfehler.

Ich kann also nicht herausfinden, was die Ursache dieses Problems ist. Können Sie einen Rat geben?

Oberflächlich betrachtet scheint es wie erwartet zu funktionieren, also nehme ich an, dass das Problem außerhalb des Codes liegt. Können Sie Schritt 1 näher erläutern? Wie genau gehen Sie bei "Vertrag aus erster Adresse in testRPC erstellen" vor? Kopieren Sie Bytecode aus Remix, stellen Sie Remix bereit, kompilieren/bereitstellen Sie mit Truffle oder etwas anderem? Es gibt einige Unklarheiten mit pragma ^0.4.13und Ihrem Prozess. Ich vermute, Sie haben Versionsinkompatibilitäten zu klären. Ein Vorschlag ist, die Beschwerden zu beseitigen ^und die daraus resultierenden Beschwerden zu lösen, indem die Dinge in eine starke explizite Ausrichtung gebracht werden. Ich hoffe es hilft.

Antworten (4)

end() Methode dieses Vertrages sollte zahlbar sein, da innerhalb der Methode eine Übertragung stattfindet. Und verwenden Sie auch safeMath.sol von OpenZeppelin für alle mathematischen Berechnungen innerhalb des Vertrags. Ich schreibe den Code um. Finden Sie bitte:

safeMath.sol

pragma solidity ^0.4.21;

/**
 * @author OpenZeppelin
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
library SafeMath {
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a * b;
        assert(a == 0 || c / a == b);
        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // assert(b > 0); // Solidity automatically throws when dividing by 0
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold
        return c;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        assert(b <= a);
        return a - b;
    }

    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        assert(c >= a);
        return c;
    }
}

escrow.sol

pragma solidity ^0.4.21;

import './safeMath.sol';

contract Escrow {

    using SafeMath for uint;

    address public owner;
    uint public fee;

    mapping (address =>  mapping (address => uint)) public balances;

    function Escrow() public {
        owner = msg.sender;
    }

    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    //Fee should be set in PPM
    function setFee(uint price) onlyOwner external {
        fee = price;
    }

    function start(address payee) payable external {
        balances[msg.sender][payee] = balances[msg.sender][payee] + msg.value;
    }

    function end(address payer, address payee) onlyOwner payable external {
        uint value = balances[payer][payee];
        uint paidFee = value.div(uint(1000000).div(fee));
        uint payment = value.sub(paidFee);
        payee.transfer(payment);
        owner.transfer(paidFee);
        balances[payer][payee] = 0;
        payee.transfer(value);
    }
}

Der Code, den Sie hier eingefügt haben, funktioniert gut, mit Ausnahme des vergessenen ;at payee.transfer(value).

Ich vermute, dass Sie, wie der Fehler sagt, einfach nicht genug Gas gegeben haben.

Geben Sie hier die Bildbeschreibung ein

Wie konnten Sie in Remix eine Gasmenge einstellen?
Übrigens verwende ich Ganache als meinen Test-RPC, also ist die Umgebung ein Web3-Anbieter
Oben rechts. "Gaslimit" und "wei" (das Sie in Äther ändern können) ermöglichen Ihnen, Ihren Sender zu "konfigurieren".
Ich weiß, dass ich das Gaslimit erhöhen kann, was ich auch getan habe. Sie sagen, dass ich auch etwas eth in die Wertform einfügen sollte?

Ich denke, Sie müssen das Von-Konto in Schritt 4 hinzufügen, wie Sie es in Schritt 2 getan haben, aber ohne Wert. Andernfalls weiß es nicht, welches Konto für Benzin belastet werden soll.

Danke für die Idee. Ich mache das von der Remix-IDE aus, daher ist ein From-Wert erforderlich, und ich habe es vom Besitzer aus gemacht.
Es wurde für mich mit der JavaScript-VM ausgeführt. Haben Sie andere Umgebungen getestet? Screenshot: imgur.com/a/Gf0fjqu
Güte. Ich habe mir so lange den Kopf darüber zerbrochen, und es scheint ein Problem mit meinem testRPC zu sein. Es funktioniert gut von der Javascript-VM. Hast du eine Ahnung, woran das liegen könnte?
Versuchen Sie, "ethereum testrpc out of gas" zu googeln. Es gibt mehrere Beiträge mit einem ähnlichen Problem.

Aus deinem Code

function start(address payee) payable external {
    balances[msg.sender][payee] = balances[msg.sender][payee] + msg.value;
  }

Um diese Funktion aufzurufen,

start("0xb631fc401038e191fa38c4ff20dcce8d13eb6ebc" , { from "0x1c34d277b51ec49536fe7843e289933e0f8020ed", value: 2000000000000000000000 })

Sie haben Wert übergeben und jetzt wird Ihr Wert nach dem Hinzufügen endgültig valuegespeichert . Springen wir zur zweiten Funktionbalances[msg.sender][payee]

function end(address payer, address payee) onlyOwner external {
    uint value = balances[payer][payee];
     payee.transfer(value);  
  }

Wenn Sie diese Funktion zum ersten Mal ausführen, wird Ihr gesamter Wert an eine Adresse des Zahlungsempfängers übertragen.
Wenn Sie diese Funktion zum zweiten Mal ausführen, haben Sie keinen Wert mehr, dann erhalten Sie den vm-Fehler.

Wenn Sie diesen Fehler nicht gemacht haben, überprüfen Sie web3js. Bitte übergeben Sie optionale Parameter.

end("0x1c34d277b51ec49536fe7843e289933e0f8020ed", "0xb631fc401038e191fa38c4ff20dcce8d13eb6ebc", {from,gasPrice,gas})

options - Object (optional): The options used for calling.
        from - String (optional): The address the call “transaction” should be made from.
        gasPrice - String (optional): The gas price in wei to use for this call “transaction”.
        gas - Number (optional): The maximum gas provided for this call “transaction” (gas limit).