Ошибка при выполнении контракта [Неверная инструкция]

Я не понимаю, почему, если я выполняю свою функцию с помощью web3.js, я получаю эту ошибку в транзакции:

Предупреждение! Ошибка при выполнении контракта [Неверная инструкция]

Я прочитал этот другой вопрос о той же ошибке. Я не понимаю, почему с этим кодом происходит то же самое:

contract Music is owned{

    string public themeMusic;
    string public idMusic;
    int public money;

    function Music (string setThemeMusic, string setIdMusic, int setmoney) {
        themeMusic = setThemeMusic;
        idMusic = setIdMusic;
        money = setmoney;
    }

    function setMoney(int moneyUpdate) onlyOwner {
        money = moneyUpdate;
    }
}

Ошибка связана с функцией setMoney для onlyOwner? мне нужно сделать это в payableлюбом случае? Я не хочу делать это payable, просто использую его только для набора денег, и эта функция только для владельцев.

Дополнительная информация:

  • Я заключаю другие контракты с аналогичными функциями, и у меня нет этой проблемы.
  • Этот контракт создается другим контрактом, таким как типичный пример Factory.
  • Owned - это контракт, в котором я храню адрес и проверяю, является ли он владельцем.
  • Я использую Meteor.jsи Web3.js.

Как вы взаимодействуете с контрактом? Для взаимодействия с контрактом я использую Web3.js API Эфириума.

Какую команду вы используете ? Я определяю контракт с ABI и адрес контракта, как это, myContract = web3.eth.contract(ABIArray).at(contractAddress);а затем я вызываю функцию контракта, как это myContract.setMoney(money);(и функцию обратного вызова).

Используете ли вы производственный блокчейн? Я работаю в тестовой сети Ropsten.

Моя музыкальная компания:

contract musicCompany is owned {

    address[] public listofmusic;

    function addMusic(string setThemeMusic, string setIdMusic, int setmoney) onlyOwner {
        address newMusic = new Music(setThemeMusic, setIdMusic, setmoney);
        listofmusic.push(newMusic);
    }
}

Этот контракт может создавать новые музыкальные контракты.

Мой собственный контракт:

contract owned {

    address public owner;

    function owned() {
        owner = msg.sender;
    }

    modifier onlyOwner {
        if (msg.sender != owner) throw;
        _;
    }

}

Мой код Web3.js:

'click .setMoney'(event, instance) {
     var price = document.getElementById('priceUpdate').value;
     event.preventDefault();
     alert("contract price");
     myContract.setMoney(price, function(error, result){
      if(!error)
          console.log(result);
      else
          console.error(error);
      })

Скриншот транзакций метамаски без проблем:

Скриншот транзакций метамаски без каких-либо проблем

Скриншот транзакции EtherScan.io с ошибкой:Скриншот транзакции EtherScan.io с ошибкой:

Обновление 1: я пытаюсь использовать целые числа без знака и байты32 вместо int, результат тот же. Может проблема в модификаторе?

Обновление 2: я попытался удалить onlyOwnerмодификатор функции и не работает...

Обновление 3: я попытался удалить все модификаторы is ownedи onlyOwnerвсе еще не работает. Я думаю, что проблема связана с функцией Builder, я сейчас начну тестировать ее...

Обновление 4: Выполняя тест, я знаю, что moneyUpdateзначение правильное и moneyодинаковое, но я обнаружил, что значение moneyне меняется. И я также обнаружил, что когда я печатаю переменную результата моего обратного вызова внутри «Мой код Web3.js», я получаю адрес транзакции 0x0fda5d31d02c87aa20c45a54f6859c7576b4f0aae4a639c47ec23e5c4e‌​3d9953. В принципе, транзакция выполняется, но ошибка препятствует изменению.

Некоторые транзакции (все мои) для просмотра ошибки:

0x52ef9164750c4e174cba1a5f45343220458f1cedca25380f0aaf102df0a8f895

0x4e00d9d67ffb906e0036434ea2e14acea82a6aabb4d8c99d94c0b2bcdef24f7a

0x4663fa874993d54989d073f72d6846cae652a454349e62882dccc96d78528a8e

0x69fbf54ffd81ee114efcd750d4e97bb528ecc868140abdecf218e9ae66391a5

Можете ли вы предоставить ссылку на одну из неудачных транзакций?
да у вас есть один в ответ, но я могу поставить больше.
Как правило, я рекомендую использовать Truffleframework для разработки. github.com/trufflesuite/truffle Это сразу устраняет многие подобные проблемы и помогает вам работать более свободно.
@NikitaFuchs Да, я знаю фреймворк, но эта разработка началась с метеора ... Теперь я не могу измениться или есть простая миграция?
С truffle вы получаете обещанные функции в соответствии с именами функций в вашем контракте, проще не бывает.

Ответы (4)

Код настолько очевидно прост, что кажется, что единственная проблема связана с onlyOwner. Я бы проверил значение ownerпеременной. Бьюсь об заклад, это не то, что вы думаете. (Это либо ноль, либо значение отправителя, развернувшего контракт). Вы не указали адрес контракта, поэтому я не могу проверить стоимость ownerна Etherscan. Кроме того, вы не предоставляете адрес вызывающей учетной записи. Если они не совпадают, транзакция будет брошена, что (как и во всех ошибках Ethereum) сообщит об отсутствии газа. Если код действительно так прост, как вы говорите, единственная возможная проблема связана с owner. Я бы проверил это.

Я попробую, а затем кое-что прокомментирую, я добавлю несколько транзакций на вопрос, хотите ли вы проверить это.
Я удаляю все ссылки на класс владельца в этом контракте и в контракте, который создал музыкальный контракт, и он работает, но если я добавлю снова, это не удастся... Что происходит?
Во время инициализации переменная владельца либо устанавливается на адрес учетной записи, отличный от того, который вы думаете, либо вообще не устанавливается (и, следовательно, равна нулю). Вы должны быть в состоянии сказать, используя вкладку «ReadContract» на etherscan.io. Кто-то прокомментировал выше, что в вашем коде не было конструктора, который, я думаю, означает, что «владелец» равен нулю. Какой адрес? Я могу проверить это.
Вам нужно предоставить полный исходный код контракта или ссылку на него через GitHub или что-то в этом роде. Если он работает без isOwner, и не работает с ним, то значение ownermsg.sender не устанавливается. (Если вы посмотрите на контракт владельца, вы увидите, что isOwnerон выбрасывает, только если значения не совпадают. Причина этого в том, что вы, скорее всего, не устанавливаете owner. Может быть, я что-то упускаю. См. Фактический полный источник, который поможет .
Да, я исправил это, с вашим советом адрес, указанный в «isOwner», не совпадает с контрактом Music, поэтому, когда я использую модификатор «onlyOwner», это не работает, потому что этот адрес является родительским контрактом. Этот сбой заставляет меня много раз изменять весь код... просто из-за неправильного адреса.
Задается ownerв конструкторе с помощью msg.sender, который является адресом учетной записи, которая развернула контракт. Если вы вызываете функцию, защищенную isOwnerпозже, и адрес, который инициирует этот вызов, не совпадает с адресом, который развернул контракт, это вызовет ошибку. Мне кажется, что вы, возможно, решили удалить, isOwnerчто, возможно, не лучшая идея. Вы должны позвонить от надлежащего владельца, иначе вы потеряете защиту, которую ownedобеспечивает контракт. Спасибо за награду.
Нет, не беспокойтесь об isOwner, я тестирую, чтобы исправить проблему, isOwnerно моя основная проблема «Определить, где проблема и почему это происходит» решена. Теперь у меня другая проблема с адресами, которые выполняют функцию, и почему они не совпадают с другими. Я помещу последнюю часть моего кода, если у вас есть идея, что это неправильно.
Обновлено последней частью взаимодействия с контрактами, вот и все. Если у вас есть идея, можете ответить мне комментарием. (Возможно проблема была в создании контракта, сейчас тестирую)
На этом этапе я бы посоветовал вам значительно упростить вопрос и задать новый вопрос, и они получат больше ответов от других людей.

Ваша транзакция, похоже, не удалась, потому что вы вызываете ее с адреса, отличного от того, с которым вы ее создали. Я прошел через первую транзакцию и заметил, что она пропускает проверку на равенство ( ISZERO + JUMPI) при сравнении с вызывающим кодом. Конечно же, эта транзакция была отправлена ​​из 0x178597064fc55ea505c3ea066c154d92bc264943, но контракт был создан0xc2351205ee14cdb8b61ffc826ad1906bc7c08755

Итак, как написал Томас , проблема действительно связана с onlyOwnerмодификатором.

Было бы полезно увидеть код ownedконтракта, от которого наследуется ваш. Я полагаю, что это не намного больше, чем установлено ownerв msg.sender, но там могут быть некоторые дополнительные сложности.

Несмотря на это, если вы попытаетесь отправить 0xc2351205ee14cdb8b61ffc826ad1906bc7c08755контракт из в первую транзакцию, это должно сработать.

В дополнение к более подробной информации, которая была бы неплохой (Как вы взаимодействуете с контрактом? Какую команду вы используете?), вам нужно добавить в контракт функцию-конструктор. Кроме того, попробуйте использовать целые числа без знака вместо int.

contract Music is owned{

    string public themeMusic;
    string public idMusic;
    int public money;

    function Music() {
    // this is the constructor, do something here or leave it empty
    }
    function Car (string setThemeMusic, string setIdMusic, uint setmoney) {
        themeMusic = setThemeMusic;
        idMusic = setIdMusic;
        money = setmoney;
    }

    function setMoney(uint moneyUpdate) onlyOwner {
        money = moneyUpdate;
    }
Извините, автомобиль - это неправильное название функции, автомобиль - это конструктор музыки, который вызывается для другой функции в другом контракте, который генерирует контракты. Исправляю в вопросе.

Я проверил ваш код, и он отлично работает (я поместил ownedчасть в тот же файл). Я использовал trufflewith testrpc(я написал и запустил тест JS). Возможно, проблема в том, как вы развертываете/взаимодействуете со своим контрактом.

Примечание: функция должна быть, payableкогда вы отправляете эфир, вызывая ее (вы хотите получить эфир, вызывая функцию). Здесь вы не отправляете реальные деньги, вы просто устанавливаете значение.

Я использую meteor.js, и эта структура отлично работает в других моих контрактах с той же функцией set и теми же функциями web3.js API, и здесь, когда я выполняю эту функцию (потому что только эта функция не работает, другие функции работают хорошо) появляется эта ошибка в etherscan, и транзакция не обрабатывается должным образом, поэтому я не могу поменять деньги.
Вы уверены, что priceотправляете в setMoney целочисленное значение? Вы пробовали с жестко заданным значением, например, 10?
Эй, Лукаш, я пытаюсь жестко закодировать значение, и происходит то же самое, но когда я использую сканирование Ethereum для просмотра транзакции, я получаю при вводе данных число, но оно в шестнадцатеричном формате, это нормально? как это:[0]:000000000000000000000000000000000000000000000000000000000000000a
@Gawey, я действительно не знаю. Попробуйте описанную ниже процедуру. 1. Что выводит функция обратного вызова? 2. Попробуйте сгенерировать событие (которое будет содержать значение moneyи moneyUpdate) после установки значения, а затем захватить событие в браузере и распечатать его. 3. Попробуйте прочитать денежную стоимость из контракта. Возможно, он был обновлен, и это просто ошибка Etherscan. 4. Используете ли вы производственный блокчейн?
для вопросов 2) и 3) все хорошо, moneyUpdateзначение правильное и moneyодинаковое, но я обнаружил, что значение moneyне меняется. Для 4) я работаю в тестовой сети Ropsten. Что касается 1) я обнаружил, что когда я печатаю resultпеременную своего обратного вызова внутри «Моего кода Web3.js», я получаю адрес транзакции 0x0fda5d31d02c87aa20c45a54f6859c7576b4f0aae4a639c47ec23e5c4e3d9953, какая-то идея? В принципе, транзакция выполняется, но ошибка препятствует изменению.
Пока нет лучшей идеи. Просто дайте мне знать, когда вы исправите это, мне любопытно, что было не так.
Хорошо, спасибо, я предложу награду за ответ хахахаха