简体   繁体   English

Solidity - Truffle:错误:处理事务时出现 VM 异常:无效的操作码不是因为恢复

[英]Solidity - Truffle: Error: VM Exception while processing transaction: invalid opcode NOT because of revert

I am working on a smart contract, and I am testing it by deploying it on truffle.我正在开发一个智能合约,我正在通过将其部署在 truffle 上来测试它。 While it compiles fine, when I call the train() function, I get the following error:虽然编译正常,但当我调用 train() 函数时,出现以下错误:

Error: VM Exception while processing transaction: invalid opcode错误:处理事务时出现 VM 异常:操作码无效

After reading a bit on this, I understood it is usually caused after a revert has occurred, so I tried commenting out the 2 require functions I had just to see if it would behave differently, and it did not.在阅读了一些关于此的内容后,我了解到它通常是在发生还原后引起的,因此我尝试注释掉 2 个 require 函数,我只是想看看它的行为是否会有所不同,但事实并非如此。

Checking out this question did not help me, or I did not see how it could.检查这个问题对我没有帮助,或者我没有看到它怎么可能。

Here is the train() function, as well as the mapping and struct type I am using in it.这是 train() 函数,以及我在其中使用的映射和结构类型。 I should note that upon creation of a Developer, their wallet is set to 300 so I do not see how the first call of the train function by the owner could revert.我应该注意到,在创建开发人员时,他们的钱包设置为 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;
}

Thank you for any help.感谢您的任何帮助。

This is most likely because you are trying to access the first entry of an empty array.这很可能是因为您正在尝试访问空数组的第一个条目。 You're using a do while loop, and you're trying to access developers_all[h].skills[i] before you're checking developers_all[h].skills.length == 0 , so it is possible that the array is empty at the first if statement in the do while.您正在使用 do while 循环,并且您在检查developers_all[h].skills.length == 0之前尝试访问developers_all[h].skills[i] ,因此该数组可能是do while 中的第一个 if 语句为空。

You could rewrite the code to something like the following, to make sure you're never accessing an unassigned array slot.您可以将代码重写为如下所示的内容,以确保您永远不会访问未分配的数组槽。

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);
}

Do note that looping through the whole array and doing the comparisons is quite costly, and can become impossible if the array size gets too big.请注意,遍历整个数组并进行比较的成本非常高,如果数组大小过大,则可能变得不可能。 You might want consider changing the structure to something like:您可能需要考虑将结构更改为:

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

That way you could just replace the whole thing with这样你就可以用

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

But you wouldn't be able to loop over the skills.但是您将无法循环使用这些技能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 松露错误:错误:处理事务时VM异常:恢复 - Truffle error: Error: VM Exception while processing transaction: revert 处理事务时VM异常:PromiEvent上的操作码无效 - VM Exception while processing transaction: invalid opcode at PromiEvent 在松露控制台中使用OpenZeppelin ERC721 Mint时,“处理事务时发生VM异常:还原” - “VM Exception while processing transaction: revert” when using OpenZeppelin ERC721 mint in truffle console Chainlink 返回错误:处理事务时出现 VM 异常:还原 - Chainlink Returned error: VM Exception while processing transaction: revert 处理事务时出现 VM 异常:还原 - VM Exception while processing transaction: revert 错误:返回错误:处理事务时 VM 异常:还原只有所有者可以调用此 function - Error: Returned error: VM Exception while processing transaction: revert only owner can call this function brownie:ValueError: execution reverted: VM Exception while processing transaction: revert - brownie:ValueError: execution reverted: VM Exception while processing transaction: revert 错误:返回错误:处理事务时出现 VM 异常:使用 New 创建时恢复 - Error: Returned error: VM Exception while processing transaction: revert when creating with New Openzepplin众包合同获得:处理事务时VM异常:恢复错误 - Openzepplin crowdsale contract got: VM Exception while processing transaction: revert error 返回错误:VM Exception while processing transaction: revert only owner can call this function - Returned error: VM Exception while processing transaction: revert only owner can call this function
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM