Fehler: VM-Ausnahme beim Verarbeiten der Transaktion: ungültiger Opcode

Ich teste den Crowdsale-Vertrag von https://ethereum.org/crowdsale auf einem lokalen Testrpc und kann nicht herausfinden, wie ich Geld dorthin senden kann. So wie ich es verstehe, erhält die anonyme Fallback-Funktion die an den Vertrag gesendeten Gelder. Die sendTransactionMethode ist nicht direkt auf der Vertragsinstanz verfügbar, daher habe ich einige andere Optionen ausprobiert (und die Dokumentation gelesen und viel gegoogelt).

Irgendwelche Vorschläge?

Hier ist das Javascript:

const cl = console.log; cl; // avoid lint error
// const Web3 = require("web3");

if (typeof global.web3 !== 'undefined') {
  global.web3 = new Web3(web3.currentProvider);
} else {
  // set the provider you want from Web3.providers
  global.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
}

const web3 = global.web3;
web3.eth.defaultAccount = web3.eth.accounts[0];

var ifSuccessfulSendTo = web3.eth.accounts[1] /* var of type address here */ ;
var fundingGoalInEthers = 20 /* var of type uint256 here */ ;
var durationInMinutes = 10 /* var of type uint256 here */ ;
var etherCostOfEachToken = 0.2 /* var of type uint256 here */ ;
var addressOfTokenUsedAsReward = web3.eth.accounts[2] /* var of type address here */ ;

var browser_cs_sol_crowdsaleContract = web3.eth.contract([{"constant":false,"inputs":[],"name":"checkGoalReached","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"deadline","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"beneficiary","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tokenReward","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"fundingGoal","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"amountRaised","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"price","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"safeWithdrawal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"ifSuccessfulSendTo","type":"address"},{"name":"fundingGoalInEthers","type":"uint256"},{"name":"durationInMinutes","type":"uint256"},{"name":"etherCostOfEachToken","type":"uint256"},{"name":"addressOfTokenUsedAsReward","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"recipient","type":"address"},{"indexed":false,"name":"totalAmountRaised","type":"uint256"}],"name":"GoalReached","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"backer","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"isContribution","type":"bool"}],"name":"FundTransfer","type":"event"}]);
var browser_cs_sol_crowdsale = browser_cs_sol_crowdsaleContract.new(
   ifSuccessfulSendTo,
   fundingGoalInEthers,
   durationInMinutes,
   etherCostOfEachToken,
   addressOfTokenUsedAsReward,
   {
     from: web3.eth.defaultAccount, 
     // from: web3.eth.accounts[3], 
     data: '0x60606040526000600760006101000a81548160ff0219169083151502179055506000600760016101000a81548160ff021916908315150217905550341561004557600080fd5b60405160a080610a4e833981016040528080519060200190919080519060200190919080519060200190919080519060200190919080519060200190919050505b846000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550670de0b6b3a76400008402600181905550603c83024201600381905550670de0b6b3a7640000820260048190555080600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50505050505b6109038061014b6000396000f30060606040523615610097576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301cb3b201461027757806329dcb0cf1461028c57806338af3eed146102b55780636e66f6e91461030a57806370a082311461035f5780637a3a0e84146103ac5780637b3e5e7b146103d5578063a035b1fe146103fe578063fd6b7ef814610427575b5b6000600760019054906101000a900460ff161515156100b657600080fd5b34905080600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555080600260008282540192505081905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb336004548481151561016257fe5b046040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b15156101e757600080fd5b6102c65a03f115156101f857600080fd5b5050507fe842aea7a5f1b01049d752008c53c52890b1a6daf660cf39e8eec506112bbdf633826001604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200183815260200182151515158152602001935050505060405180910390a15b50005b341561028257600080fd5b61028a61043c565b005b341561029757600080fd5b61029f61051e565b6040518082815260200191505060405180910390f35b34156102c057600080fd5b6102c8610524565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561031557600080fd5b61031d610549565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561036a57600080fd5b610396600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061056f565b6040518082815260200191505060405180910390f35b34156103b757600080fd5b6103bf610587565b6040518082815260200191505060405180910390f35b34156103e057600080fd5b6103e861058d565b6040518082815260200191505060405180910390f35b341561040957600080fd5b610411610593565b6040518082815260200191505060405180910390f35b341561043257600080fd5b61043a610599565b005b6003544210151561051b576001546002541015156104fe576001600760006101000a81548160ff0219169083151502179055507fec3f991caf7857d61663fd1bba1739e04abd4781238508cde554bb849d790c856000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600254604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15b6001600760016101000a81548160ff0219169083151502179055505b5b5b565b60035481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60066020528060005260406000206000915090505481565b60015481565b60025481565b60045481565b6000600354421015156108d357600760009054906101000a900460ff16151561074a57600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000811115610749573373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015610703577fe842aea7a5f1b01049d752008c53c52890b1a6daf660cf39e8eec506112bbdf633826000604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200183815260200182151515158152602001935050505060405180910390a1610748565b80600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b5b5b600760009054906101000a900460ff1680156107b257503373ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b156108d1576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc6002549081150290604051600060405180830381858888f19350505050156108b4577fe842aea7a5f1b01049d752008c53c52890b1a6daf660cf39e8eec506112bbdf66000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff166002546000604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200183815260200182151515158152602001935050505060405180910390a16108d0565b6000600760006101000a81548160ff0219169083151502179055505b5b5b5b5b505600a165627a7a7230582088450757203ab9947a54bcea1bbbf19594c4d831d252ff1c2df8a9999aa3ef350029', 
     gas: '4700000'
   }, function (e, contract){
    // console.log(e, contract);
    if (typeof contract.address !== 'undefined') {
         console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
    }
 })

// cl('browser_cs_sol_crowdsale',browser_cs_sol_crowdsale)
const contract = global.contract = browser_cs_sol_crowdsale;

global.go = ()=>{

  const params = {
     from: web3.eth.defaultAccount
     // from: web3.eth.accounts[5]
    ,to: contract.address
    ,value: web3.fromDecimal(20)
    // ,value: 10
    ,gas: 1000000
  };
  cl('params',params);
  // contract.beneficiary.sendTransaction( params, function(err, txHash) {
  web3.eth.sendTransaction( params, function(err, txHash) {
    if (err != null) {
     cl("Error while sending transaction: " + err);
    } else {
     cl("Transaction sent, here's your txHash: " + txHash);
    }
  });

}; // go

module.exports = web3;

Was diesen Fehler erzeugt, wenn es go()von der Konsole ausgeführt wird:

Error: VM Exception while processing transaction: invalid opcode

Hier ist der aktuelle Vertrag:

pragma solidity ^0.4.16;
// https://ethereum.org/crowdsale

interface token {
    function transfer(address receiver, uint amount);
}

contract Crowdsale {
    address public beneficiary;
    uint public fundingGoal;
    uint public amountRaised;
    uint public deadline;
    uint public price;
    token public tokenReward;
    mapping(address => uint256) public balanceOf;
    bool fundingGoalReached = false;
    bool crowdsaleClosed = false;

    event GoalReached(address recipient, uint totalAmountRaised);
    event FundTransfer(address backer, uint amount, bool isContribution);

    /**
     * Constrctor function
     *
     * Setup the owner
     */
    function Crowdsale(
        address ifSuccessfulSendTo,
        uint fundingGoalInEthers,
        uint durationInMinutes,
        uint etherCostOfEachToken,
        address addressOfTokenUsedAsReward
    ) {
        beneficiary = ifSuccessfulSendTo;
        fundingGoal = fundingGoalInEthers * 1 ether;
        deadline = now + durationInMinutes * 1 minutes;
        price = etherCostOfEachToken * 1 ether;
        tokenReward = token(addressOfTokenUsedAsReward);
    }

    /**
     * Fallback function
     *
     * The function without name is the default function that is called whenever anyone sends funds to a contract
     */
    function () payable {
        require(!crowdsaleClosed);
        uint amount = msg.value;
        balanceOf[msg.sender] += amount;
        amountRaised += amount;
        tokenReward.transfer(msg.sender, amount / price);
        FundTransfer(msg.sender, amount, true);
    }

    modifier afterDeadline() { if (now >= deadline) _; }

    /**
     * Check if goal was reached
     *
     * Checks if the goal or time limit has been reached and ends the campaign
     */
    function checkGoalReached() afterDeadline {
        if (amountRaised >= fundingGoal){
            fundingGoalReached = true;
            GoalReached(beneficiary, amountRaised);
        }
        crowdsaleClosed = true;
    }


    /**
     * Withdraw the funds
     *
     * Checks to see if goal or time limit has been reached, and if so, and the funding goal was reached,
     * sends the entire amount to the beneficiary. If goal was not reached, each contributor can withdraw
     * the amount they contributed.
     */
    function safeWithdrawal() afterDeadline {
        if (!fundingGoalReached) {
            uint amount = balanceOf[msg.sender];
            balanceOf[msg.sender] = 0;
            if (amount > 0) {
                if (msg.sender.send(amount)) {
                    FundTransfer(msg.sender, amount, false);
                } else {
                    balanceOf[msg.sender] = amount;
                }
            }
        }

        if (fundingGoalReached && beneficiary == msg.sender) {
            if (beneficiary.send(amountRaised)) {
                FundTransfer(beneficiary, amountRaised, false);
            } else {
                //If we fail to send the funds to beneficiary, unlock funders balance
                fundingGoalReached = false;
            }
        }
    }
}

Antworten (1)

Eines der Probleme könnte darin bestehen, dass Sie tokenReward (die Adresse des Tokens, das Sie für die Verteilung verwenden) auf eines der eth-Konten festlegen, bei dem es sich um ein externes Konto (einen Benutzer) handelt. Der Crowdsale-Vertrag erfordert, dass Sie zuerst den Token-Vertrag bereitstellen, seine Adresse notieren und diese Adresse an den Crowdsale-Konstruktor weitergeben müssen.

Dies führt sicherlich dazu, dass es fehlschlägt, wenn Sie versuchen, die Funktion token.transfer() auf dieser Adresse auszuführen.

Ich empfehle Ihnen, all dies auf Remix anstelle von web3 auszuprobieren, damit Sie es einfach debuggen und die Funktionen jedes Vertrags aufrufen können, ohne weiteren Code schreiben zu müssen.

Danke. Ich habe vergessen zu erwähnen, dass Ethereum und Solidität für mich völlig neu sind - und ich hatte gehofft, mich nur auf den JavaScript-Teil zu konzentrieren, indem ich ein Backend verwende, das bereits sofort einsatzbereit ist. Was Sie oben erklären, übersteigt derzeit mein Verständnis von Solidität.
Wollen Sie damit sagen, dass ich zuerst die bereitstellen interface token, ihre Adresse abrufen und diese Adresse an den Vertragskonstruktor übergeben sollte - als welcher Parameter? Und wie ermöglicht Remix die Übergabe von Werten an den Konstruktor?
Ich würde empfehlen andersherum anzufangen. Erstens, weil dieser Beispielvertrag auf der Website von Ethereum noch lange nicht produktionsreif ist, ist er weit davon entfernt, perfekt zu sein. Zweitens, wenn Sie nicht verstehen, was im Solidity-Code passiert, wissen Sie nicht, welche Parameter Sie vom Front-End bereitstellen müssen.
Danke, irgendwelche Vorschläge, wo ich anfangen soll?
Die Operation ist richtig, Sie verwenden eine EOA ( web3.eth.accounts[2] ) als Token-Adresse. Dies muss jedoch ein gültiger (ERC20) Token sein, der vor dem Crowdsale Smart Contract eingesetzt wird. Gehen Sie wahrscheinlich das Token-Beispiel auf der Website durch und gehen Sie dann erneut zum Crowdsale-Beispiel. Die Schnittstelle tokenwird verwendet, damit Sie die transfer(...)Funktion auf dem zuvor bereitgestellten ERC20-Token aufrufen können. Die ersten Argumente von transfer(...)sollten dann das Zielkonto sein, auf das Sie Token übertragen möchten.