Solidity - Truffle:Error:VM异常处理事务时:无效操作码因为还原而无效

问题描述 投票:0回答:1

我正在制定一份智能合约,我正在通过将其部署在松露上进行测试。虽然编译很好,但当我调用train()函数时,我收到以下错误:

错误:处理事务时出现VM异常:操作码无效

在阅读了这一点之后,我明白它通常是在一个恢复发生之后引起的,所以我试着评论出2个需要的函数,我只是看它是否会表现不同,而事实并非如此。

检查this问题没有帮助我,或者我没有看到它怎么可能。

这是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;
}

感谢您的任何帮助。

ethereum solidity smartcontracts opcode truffle
1个回答
0
投票

这很可能是因为您尝试访问空数组的第一个条目。您正在使用do while循环,并且在检查developers_all[h].skills[i]之前尝试访问developers_all[h].skills.length == 0,因此有可能在do while中的第一个if语句处该数组为空。

您可以将代码重写为以下内容,以确保您永远不会访问未分配的数组插槽。

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]++;

但是你无法绕过这些技能。

© www.soinside.com 2019 - 2024. All rights reserved.