Солидность - трюфель: ошибка: исключение виртуальной машины при обработке транзакции: неверный код операции НЕ из-за возврата - PullRequest
0 голосов
/ 23 февраля 2019

Я работаю над умным контрактом и проверяю его, развернув его на трюфеле.Хотя он хорошо компилируется, при вызове функции train () я получаю следующую ошибку:

Ошибка: исключение виртуальной машины при обработке транзакции: недопустимый код операции

После чтениянемного об этом, я понял, что это обычно вызывается после того, как произошел возврат, поэтому я попытался закомментировать 2 функции require, которые у меня были, просто чтобы посмотреть, будет ли он вести себя по-другому, и это не так.

Проверка этот вопрос не помог мне, или я не видел, как это могло быть.

Вот функция train (), а также отображение иТип структуры я использую в нем.Я должен отметить, что при создании разработчика их кошелек был настроен на 300, поэтому я не вижу, как первый вызов функции поезда может быть восстановлен владельцем.

struct Developer {
    address owner;
    string name;
    bytes32 namehash;
    bytes32[] skills;
    uint256[] skill_levels;
    uint wallet;
}

mapping (bytes32=>Developer) public developers_all;

function train(string _name, bytes32 _skill) public {
    bytes32 h = keccak256(abi.encodePacked(_name));

    require(developers_all[h].owner == msg.sender, "Only the owner of the developer can train them");
    require(developers_all[h].wallet >= 150, "Insufficient funds");

    uint256 i = 0; 

    do {
        if (developers_all[h].skills[i] == _skill) {
            developers_all[h].skill_levels[i]++;
        } else if ((i == (developers_all[h].skills.length - 1)) || (developers_all[h].skills.length == 0)) {
            developers_all[h].skills.push(_skill);
            developers_all[h].skill_levels.push(1);
        }
        i++;
    } while (i < developers_all[h].skills.length);

    developers_all[h].wallet = developers_all[h].wallet - 150;
}

Спасибо за любую помощь.

1 Ответ

0 голосов
/ 24 февраля 2019

Это наиболее вероятно, потому что вы пытаетесь получить доступ к первой записи пустого массива.Вы используете цикл do while и пытаетесь получить доступ к developers_all[h].skills[i] перед проверкой developers_all[h].skills.length == 0, поэтому возможно, что массив будет пустым в первом операторе if в do while.

Вы можете переписать код примерно так, как показано ниже, чтобы убедиться, что вы никогда не получите доступ к неназначенному слоту массива.

bool foundSkill = false;

for (uint i = 0; i < developers_all[h].skills.length; i++) {
    if (developers_all[h].skills[i] == _skill) {
        developers_all[h].skill_levels[i]++;
        foundSkill = true;
        break;
    }
}

if (!foundSkill) {
    developers_all[h].skills.push(_skill);
    developers_all[h].skill_levels.push(1);
}

Обратите внимание, что цикл по всему массиву и выполнениеСравнение довольно дорого и может стать невозможным, если размер массива становится слишком большим.Возможно, вы захотите изменить структуру на что-то вроде:

struct Developer {
    address owner;
    string name;
    bytes32 namehash;
    mapping(bytes32 => uint) skill_levels;
    uint wallet;
}

Таким образом, вы можете просто заменить все это на

developers_all[h].skill_levels[skill]++;

Но вы не сможете перебратьнавыки.

...