Remix
(Remix IDE) 獲取 VM 錯誤:Javascript VM 中的操作碼無效,
我正在創建一個 ERC20 代幣,它將有 9 輪單獨的融資。當我在 JavaScript VM 中呼叫 startNextRound 函式時,我收到以下錯誤:
transact to browser/SatanCoin.sol:SatanCoin.startNextRound errored: VM error: invalid opcode. The constructor should be payable if you send value. The execution might have thrown. Debug the transaction to get more information. creation of browser/SatanCoin.sol:SatanCoin pending...
當我通過 Remix 在 Rinkeby 上部署相同的合約並呼叫相同的函式時,交易耗盡了 gas:
transact to browser/SatanCoin.sol:SatanCoin.startNextRound errored: Gas required exceeds limit: 3000000. An important gas estimation might also be the sign of a problem in the contract code. Please check loops and be sure you did not sent value to a non payable function (that's also the reason of strong gas estimation)
當我使用 Remix 調試器時,它告訴我函式在
require(msg.sender == owner);
. 這裡到底出了什麼問題?這是程式碼。我從 openZepplin 繼承 StandardToken。
contract TestCoin is StandardToken { uint256 public rate = 0.0666 ether; //Each Testcoin will be worth .0666 ETH, Must be bought in exact increments address public owner = msg.sender; bool public roundActive = false; //only allows buying during a round uint public roundNum = 0;//current round number out of 9 uint public roundMax = 74;//max number of tokens to be issued every round uint public roundIssued;//number of tokens issued during current or previous round address[] roundBuyers; //buyer address is recorded for every token issued modifier onlyOwner { require(msg.sender == owner); _; } event Raffled(uint roundNumber, address winner, uint amount); event RoundStart(uint roundNumber); function name() constant returns (string) { return "TestCoin"; } function symbol() constant returns (string) { return "TEST"; } function decimals() constant returns (uint8) { return 0; } function startNextRound() public { require(msg.sender == owner); assert(endPreviousRound()); //end the previous round before starting the next require(roundNum<9); //only 9 rounds may occur roundActive = true; roundBuyers = new address[](74); roundIssued = 0; roundNum++; RoundStart(roundNum); } function endPreviousRound() private returns (bool) { //raffles off remaining tokens if any are left if(roundIssued < roundMax) assert(raffle(amountRemaining())); roundActive = false; return true; } //raffles off remainig tokens to a random buyer from the previous round //the more tokens a buyer has, the greater their chance to win function raffle(uint raffleAmount) private returns (bool) { uint randomIndex = uint(block.blockhash(block.number))%(roundMax-raffleAmount)+1; mint(roundBuyers[randomIndex], raffleAmount); Raffled(roundNum, roundBuyers[randomIndex], raffleAmount); } function mint(address receiver, uint amount) private { totalSupply = safeAdd(totalSupply, amount); balances[receiver] = safeAdd(balances[receiver], amount); for(uint i = 0; i < amount; i++) { roundBuyers[roundIssued+i] = receiver; } roundIssued = safeAdd(roundIssued, amount); // This will make the mint transaction apper in EtherScan.io Minted(receiver, amount); } //This function is called when Ether is sent to the contract address //Even if 0 ether is sent. function () payable { //If value is zero or not multiple of the rate, refund user. if (msg.value <= 0 || (msg.value % rate) != 0) revert(); uint tokenAmount = safeDiv(msg.value, rate); //Make sure there is an active round if(roundActive == false) revert(); //Make sure a buyer can't buy more than round amount availible. if (tokenAmount > amountRemaining()) revert(); //Make sure that no more than 666 TestCoins can be issued. if ((tokenAmount+totalSupply) > 666) revert(); //Extra precaution to contract attack if (tokenAmount < 1) revert(); mint(msg.sender, tokenAmount); owner.transfer(msg.value); //Send the ETH } //returns number of tokens left to be issued in current round function amountRemaining() public constant returns (uint) { return (roundMax-roundIssued); } }
如果函式由於 requires/assert/throw 呼叫而失敗,您將收到有關用盡 gas 或 vm 無效操作碼的錯誤。
因此,如果調試顯示執行停止在 require(msg.sender == owner); 那麼唯一可能的解釋是您使用不是所有者的帳戶呼叫此函式。
據我所知,“無效操作碼”消息的原因通常是變數為空。我認為在您的情況下,以下行不正確:
address public owner = msg.sender;
這麼說的時候
contract TestCoin is StandardToken
“所有者”變數已由 StandardToken-Contract 的建構子設置。
因此,也許您應該將上面的行更改為:
address public owner;
希望能幫助到你。