Ошибка: код контракта не может быть сохранен, проверьте количество газа

Я использую приведенный ниже код для создания контакта, который выдает ошибку:

Error: The contract code couldn't be stored, please check your gas amount.

Код:

primaryAccount = web3.eth.accounts[0];

//Multisignature source code
var testSource=' contract multiowned { struct PendingState { uint yetNeeded; uint ownersDone; uint index; } event Confirmation(address owner, bytes32 operation); event Revoke(address owner, bytes32 operation); event OwnerChanged(address oldOwner, address newOwner); event OwnerAdded(address newOwner); event OwnerRemoved(address oldOwner); event RequirementChanged(uint newRequirement); modifier onlyowner { if (isOwner(msg.sender)) _ } modifier onlymanyowners(bytes32 _operation) { if (confirmAndCheck(_operation)) _ } function multiowned(address[] _owners, uint _required) { m_numOwners = _owners.length + 1; m_owners[1] = uint(msg.sender); m_ownerIndex[uint(msg.sender)] = 1; for (uint i = 0; i < _owners.length; ++i) { m_owners[2 + i] = uint(_owners[i]); m_ownerIndex[uint(_owners[i])] = 2 + i; } m_required = _required; } function revoke(bytes32 _operation) external { uint ownerIndex = m_ownerIndex[uint(msg.sender)]; if (ownerIndex == 0) return; uint ownerIndexBit = 2**ownerIndex; var pending = m_pending[_operation]; if (pending.ownersDone & ownerIndexBit > 0) { pending.yetNeeded++; pending.ownersDone -= ownerIndexBit; Revoke(msg.sender, _operation); } } function changeOwner(address _from, address _to) onlymanyowners(sha3(msg.data, block.number)) external { if (isOwner(_to)) return; uint ownerIndex = m_ownerIndex[uint(_from)]; if (ownerIndex == 0) return; clearPending(); m_owners[ownerIndex] = uint(_to); m_ownerIndex[uint(_from)] = 0; m_ownerIndex[uint(_to)] = ownerIndex; OwnerChanged(_from, _to); } function addOwner(address _owner) onlymanyowners(sha3(msg.data, block.number)) external { if (isOwner(_owner)) return; clearPending(); if (m_numOwners >= c_maxOwners) reorganizeOwners(); if (m_numOwners >= c_maxOwners) return; m_numOwners++; m_owners[m_numOwners] = uint(_owner); m_ownerIndex[uint(_owner)] = m_numOwners; OwnerAdded(_owner); } function removeOwner(address _owner) onlymanyowners(sha3(msg.data, block.number)) external { uint ownerIndex = m_ownerIndex[uint(_owner)]; if (ownerIndex == 0) return; if (m_required > m_numOwners - 1) return; m_owners[ownerIndex] = 0; m_ownerIndex[uint(_owner)] = 0; clearPending(); reorganizeOwners(); OwnerRemoved(_owner); } function changeRequirement(uint _newRequired) onlymanyowners(sha3(msg.data, block.number)) external { if (_newRequired > m_numOwners) return; m_required = _newRequired; clearPending(); RequirementChanged(_newRequired); } function isOwner(address _addr) returns (bool) { return m_ownerIndex[uint(_addr)] > 0; } function hasConfirmed(bytes32 _operation, address _owner) constant returns (bool) { var pending = m_pending[_operation]; uint ownerIndex = m_ownerIndex[uint(_owner)]; if (ownerIndex == 0) return false; uint ownerIndexBit = 2**ownerIndex; if (pending.ownersDone & ownerIndexBit == 0) { return false; } else { return true; } } function confirmAndCheck(bytes32 _operation) internal returns (bool) { uint ownerIndex = m_ownerIndex[uint(msg.sender)]; if (ownerIndex == 0) return; var pending = m_pending[_operation]; if (pending.yetNeeded == 0) { pending.yetNeeded = m_required; pending.ownersDone = 0; pending.index = m_pendingIndex.length++; m_pendingIndex[pending.index] = _operation; } uint ownerIndexBit = 2**ownerIndex; if (pending.ownersDone & ownerIndexBit == 0) { Confirmation(msg.sender, _operation); if (pending.yetNeeded <= 1) { delete m_pendingIndex[m_pending[_operation].index]; delete m_pending[_operation]; return true; } else { pending.yetNeeded--; pending.ownersDone |= ownerIndexBit; } } } function reorganizeOwners() private returns (bool) { uint free = 1; while (free < m_numOwners) { while (free < m_numOwners && m_owners[free] != 0) free++; while (m_numOwners > 1 && m_owners[m_numOwners] == 0) m_numOwners--; if (free < m_numOwners && m_owners[m_numOwners] != 0 && m_owners[free] == 0) { m_owners[free] = m_owners[m_numOwners]; m_ownerIndex[m_owners[free]] = free; m_owners[m_numOwners] = 0; } } } function clearPending() internal { uint length = m_pendingIndex.length; for (uint i = 0; i < length; ++i) if (m_pendingIndex[i] != 0) delete m_pending[m_pendingIndex[i]]; delete m_pendingIndex; } uint public m_required; uint public m_numOwners; uint[256] m_owners; uint constant c_maxOwners = 250; mapping(uint => uint) m_ownerIndex; mapping(bytes32 => PendingState) m_pending; bytes32[] m_pendingIndex; } contract daylimit is multiowned { modifier limitedDaily(uint _value) { if (underLimit(_value)) _ } function daylimit(uint _limit) { m_dailyLimit = _limit; m_lastDay = today(); } function setDailyLimit(uint _newLimit) onlymanyowners(sha3(msg.data, block.number)) external { m_dailyLimit = _newLimit; } function resetSpentToday() onlymanyowners(sha3(msg.data, block.number)) external { m_spentToday = 0; } function underLimit(uint _value) internal onlyowner returns (bool) { if (today() > m_lastDay) { m_spentToday = 0; m_lastDay = today(); } if (m_spentToday + _value >= m_spentToday && m_spentToday + _value <= m_dailyLimit) { m_spentToday += _value; return true; } return false; } function today() private constant returns (uint) { return now / 1 days; } uint public m_dailyLimit; uint public m_spentToday; uint public m_lastDay; } contract multisig { event Deposit(address from, uint value); event SingleTransact(address owner, uint value, address to, bytes data); event MultiTransact(address owner, bytes32 operation, uint value, address to, bytes data); event ConfirmationNeeded(bytes32 operation, address initiator, uint value, address to, bytes data); function changeOwner(address _from, address _to) external; function execute(address _to, uint _value, bytes _data) external returns (bytes32); function confirm(bytes32 _h) returns (bool); } contract Wallet is multisig, multiowned, daylimit { uint public version = 2; struct Transaction { address to; uint value; bytes data; } function Wallet(address[] _owners, uint _required, uint _daylimit) multiowned(_owners, _required) daylimit(_daylimit) { } function kill(address _to) onlymanyowners(sha3(msg.data, block.number)) external { suicide(_to); } function() { if (msg.value > 0) Deposit(msg.sender, msg.value); } function execute(address _to, uint _value, bytes _data) external onlyowner returns (bytes32 _r) { if (underLimit(_value)) { SingleTransact(msg.sender, _value, _to, _data); _to.call.value(_value)(_data); return 0; } _r = sha3(msg.data, block.number); if (!confirm(_r) && m_txs[_r].to == 0) { m_txs[_r].to = _to; m_txs[_r].value = _value; m_txs[_r].data = _data; ConfirmationNeeded(_r, msg.sender, _value, _to, _data); } } function confirm(bytes32 _h) onlymanyowners(_h) returns (bool) { if (m_txs[_h].to != 0) { m_txs[_h].to.call.value(m_txs[_h].value)(m_txs[_h].data); MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to, m_txs[_h].data); delete m_txs[_h]; return true; } } function clearPending() internal { uint length = m_pendingIndex.length; for (uint i = 0; i < length; ++i) delete m_txs[m_pendingIndex[i]]; super.clearPending(); } mapping (bytes32 => Transaction) m_txs; }'

// Solidity process
var testCompiled = web3.eth.compile.solidity(testSource);

//contract process
var testContract = web3.eth.contract(testCompiled.multisig.info.abiDefinition);

contractData = web3.eth.contract(testCompiled.multisig.info.abiDefinition).new.getData({data: testCompiled.multisig.code});
console.log("estimating gas price of creating B...");
var gasEstimate = web3.eth.estimateGas({data: contractData});
console.log(gasEstimate);

//deploying process
multisig = testContract.new({
    from:web3.eth.accounts[0], 
    data: testCompiled.multisig.code, gas: gasEstimate+3000}, 
    function(e, contract) {

     if(!e) {

    if(!contract.address) {
      console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined...");

    } else {
      //Once get this message we can call the functions
      console.log("Contract mined! Address: " + contract.address);
      console.log(contract);
    }

  }
  else
  {
    console.log(e);
  }
}); 
В testContract.new, а gas: gasEstimate+3000не вы пробовали gas: 3000000?
я проверил с газом: цена 3000000 возникает та же ошибка, только я меняю расчетный газ, теперь тоже возникла такая же проблема. Если я даю большое количество, то он говорит, что количество газа превышает. не могу понять в чем проблема
Не могли бы вы отформатировать свой код, чтобы другим людям было легче его читать и помогать? (Используйте параметр { } «Предварительно отформатированный текст».)
lesyk исправил это с помощью solc, но не использовал функцию AssessmentGas. solc, безусловно, лучший способ компиляции в наши дни, и я добавил 50000 к полученному результату AssessmentGas, и он работает! Удивительно только то, что оценка ошибается в сторону уменьшения, а не в сторону увеличения. Что они думали?

Ответы (5)

Эта ошибка возникает из-за того, что geth не всегда правильно рассчитывает стоимость хранения контракта. Попробуйте добавить 20-50000 газа и посмотрите, устранит ли это ошибку.

Пожалуйста, не стесняйтесь отправлять вопросы в репозиторий go ethereum.

Была такая же проблема, исправленная с помощью компиляции solc:

const fs = require("fs");
const Web3 = require('web3');
const solc = require('solc')

let web3 = new Web3();

let account = web3.personal.unlockAccount(web3.eth.accounts[0], 'password');
let source = fs.readFileSync('nameContract.sol', 'utf8');
let compiledContract = solc.compile(source, 1);
let abi = compiledContract.contracts['nameContract'].interface;
console.log('Abi: ', abi);
let bytecode = compiledContract.contracts['nameContract'].bytecode;
let gasEstimate = web3.eth.estimateGas({data: bytecode});
let contract = web3.eth.contract(JSON.parse(abi));
contract.new({from:web3.eth.accounts[0], data:bytecode, value:30000000000000000000, gas:gasEstimate}, function(err, myContract){
  if(!err) {
     if(!myContract.address) {
         console.log("Hash: ", myContract.transactionHash);
     } else {
         console.log("Address: ", myContract.address);
     }
  }
  else {
    console.log(err);
  }
});

Это может произойти, если вы неправильно используете наследование в своем контракте. Например,

pragma solidity ^0.4.19;

contract Base {
  uint foo;
  function Base(uint _foo) {
    foo = _foo;
  }
}

contract Derived is Base {
  function Derived() {}
}

Можете ли вы найти ошибку? Здесь наследование выполняется неправильно, потому что вам нужно указать аргументы конструктора базового контракта в производном контракте:

contract Derived is Base(28) {
  function Derived() {}
}

или же:

contract Derived is Base {
  function Derived(uint _bar) Base(_bar * 2) {}
}

На собственном горьком опыте я обнаружил еще одну причину, по которой это происходит: неудачные вызовы конструктора.

Моя установка:

  • Окна
  • Трюфель v4.1.8
  • Geth 1.8.8-стабильная
  • Запуск легкой ноды с помощью командыgeth.exe -syncmode light --testnet --rpc --rpcapi eth,net,web3,personal
  • Прикрепление Geth к geth attach http://127.0.0.1:8545учетной записи и разблокировка учетной записи
  • Бегущий трюфель сtruffle.cmd test --network ropsten

Вы получите ошибку OP (по крайней мере) с этой настройкой, если у вас есть ошибка где- requireто в конструкторе. Например:

contract A {
    constructor() public {
        require(false);
    }
}

Так что не забудьте также перепроверить свои requireзвонки.

Если вы встретите

Error: The contract code couldn't be stored, please check your gas amount.

При развертывании в частной сети через набор трюфелей может быть неправильная версия evm на удаленном узле.

Всегда проверяйте версию evm и ее отличия от производственной среды.

Также вы должны проверить, какую версию evm truffle использовать для компиляции. Его можно найти наtruffle.js