Solidity投票合约测试遇VM异常:因‘投票已开始’回滚求助
合约测试报错:"The voting has already begun!" 原因分析与修复
你的两个测试用例失败都是因为合约代码里的逻辑错误,具体问题如下:
1. editVotingPeriod函数的运算符使用错误
在editVotingPeriod函数中,你误将比较运算符==写成了赋值运算符=:
function editVotingPeriod(uint _id, uint _newPeriod) public onlyOwner { require(Votings[_id].started = false, "The voting has already begun!"); Votings[_id].Period = _newPeriod; }
这段代码会把Votings[_id].started强制设为false,然后require判断这个赋值操作的结果(false),直接触发报错。
修复方式:将=替换为==,或者用更简洁的取反写法:
require(Votings[_id].started == false, "The voting has already begun!"); // 或 require(!Votings[_id].started, "The voting has already begun!");
2. addCandidate和deleteCandidate函数的逻辑颠倒
这两个函数的require条件完全写反了:
function addCandidate(uint _id, address _candidate) public onlyOwner { // ...其他判断 require(Votings[_id].started, "The voting has already begun!"); // ... } function deleteCandidate(address _candidate, uint _id) public onlyOwner { require(Votings[_id].started, "The voting has already begun!"); // ... }
当前逻辑是"只有投票已开始,才能添加/删除候选人",但实际需求应该是"投票未开始时才能修改候选人名单"。这直接导致addVoting函数调用addCandidate时,因为新创建的投票started默认是false,触发报错。
修复方式:给条件添加取反运算符!:
// addCandidate中的判断 require(!Votings[_id].started, "The voting has already begun!"); // deleteCandidate中的判断 require(!Votings[_id].started, "The voting has already begun!");
额外测试用例问题(第一个测试)
第一个测试直接调用editVotingPeriod(0, 200),但此时ID=0的投票还未通过addVoting创建(合约会给mapping未初始化的投票设默认值,但逻辑上应该先创建再修改),同时你还搞错了getVotingInfo的返回索引。测试代码需要调整:
it("An owner can change voting's period", async function () { const { myVoting, owner } = await loadFixture(deploy); // 先创建投票 const candidates = [owner.address, ethers.Wallet.createRandom().address]; await myVoting.connect(owner).addVoting(candidates, 100); // 再修改周期 await myVoting.connect(owner).editVotingPeriod(0, 200); const _votingInfo = await myVoting.getVotingInfo(0); expect(_votingInfo[4]).to.equal(200); // Period是返回值的第5项,索引为4 });
内容的提问来源于stack exchange,提问作者aleeeexcool
相关产品推荐
相关产品推荐

