Pick Winner Lottery test throw;错误:事务已被EVM恢复



我正在写一个彩票合同,它应该接受玩家,选择一个赢家,并将收集的资金发送到赢家的地址,然后重新开始。运行npm run test后,前5个测试都通过了,但是"将钱发给获胜者"。重置播放器数组"测试失败,错误信息如下。

1) lottery Contract
sends money to the winner & resets the players array:
Error: Transaction has been reverted by the EVM:

我个人认为问题出在Lottery.test.js文件上,在这个代码片段上,因为到目前为止,一切都运行良好;

await lottery.methods.pickWinner().send({
from: accounts[0]
});

其他项目文件粘贴在下面以帮助调试。

我的彩票。索尔文件;

pragma solidity ^0.8.13;
contract Lottery {
address public manager;
address payable[] public players;
function myLottery() public {
manager = msg.sender;
}
function enter() public payable {
require(msg.value > .001 ether);
players.push(payable(msg.sender));
}
function random() private view returns(uint){
return uint(keccak256(abi.encodePacked(block.difficulty, block.timestamp, players)));
}
function pickWinner() public restricted{
uint index = random() % players.length;
players[index].transfer(address(this).balance);  
players = new address payable[](0);
}
modifier restricted() {
require(msg.sender == manager);
_;
}
function getPlayers() public view returns (address payable[] memory) {
return players;
}
}

compile.js

const path = require("path");
const fs = require("fs");
const solc = require("solc");
const lotteryPath = path.resolve(__dirname, "contracts", "Lottery.sol");
const source = fs.readFileSync(lotteryPath, "utf8");
let input = {
language: "Solidity",
sources: {
[lotteryPath]: {
content: source,
},
},
settings: {
outputSelection: {
"*": {
"*": ["*"],
},
},
},
};
var output = JSON.parse(solc.compile(JSON.stringify(input)));
module.exports = {
abi: output.contracts[[lotteryPath]]["Lottery"].abi,
bytecode: output.contracts[[lotteryPath]]["Lottery"].evm.bytecode.object,
};

deploy.js

const HDWalletProvider = require('truffle-hdwallet-provider');
const Web3 = require('web3');
const { abi, bytecode } = require("./compile");
const provider = new HDWalletProvider(
'****myMneumonic*****',
'****myInfuraNode****'
);
const web3 = new Web3 (provider);
const deploy = async () => {
const accounts = await web3.eth.getAccounts();
console.log('Attempting to deploy from account;', accounts[0]);
const result = await new web3.eth.Contract(abi)
.deploy({ data: bytecode })
.send({ from: accounts[0], gas: '10000000', gasPrice: '2000000000'});
console.log('Contract deployed to;', result.options.address);
};
deploy();

Lottery.test.js

const assert = require("assert");
const ganache = require("ganache");
const Web3 = require("web3");
const web3 = new Web3(ganache.provider());
const { abi, bytecode } = require("../compile");
let accounts;
let lottery;
beforeEach(async () => {
//get a list of all accounts
accounts = await web3.eth.getAccounts();
lottery = await new web3.eth.Contract(abi)
.deploy({ data: bytecode })
.send({ from: accounts[0], gas: "1000000" });
});
describe('lottery Contract', () => {
it ('deploys a contract', () => {
assert.ok(lottery.options.address);
});
it('allows one account to enter', async () => {
await lottery.methods.enter().send({
from: accounts[0],
value: web3.utils.toWei('0.002', 'ether')
});
const players = await lottery.methods.getPlayers().call({
from: accounts [0]
});
assert.equal(accounts[0], players);
assert.equal(1, players.length);
});
it('allows multiple accounts to enter', async () => {
await lottery.methods.enter().send({
from: accounts[0],
value: web3.utils.toWei('0.002', 'ether')
});
await lottery.methods.enter().send({
from: accounts[1],
value: web3.utils.toWei('0.002', 'ether')
});
await lottery.methods.enter().send({
from: accounts[2],
value: web3.utils.toWei('0.002', 'ether')
});
const players = await lottery.methods.getPlayers().call({
from: accounts[0]
});
assert.equal(accounts[0], players[0]);
assert.equal(accounts[1], players[1]);
assert.equal(accounts[2], players[2]);
assert.equal(3, players.length);
});
it('requires a minimum amount of ether to enter', async () => {
try {
await lottery.methods.enter().send({
from: accounts[0],
value: 200
});
assert(false);
} catch (err) {
assert(err);
}
});
it ('only manager can call pickWinner', async () => {
try {
await lottery.methods.pickWinner().send({
from: accounts[1],
value: 200
});
assert(false);
} catch (err) {
assert(err);
}
});
it('sends money to the winner & resets the players array', async () =>{
await lottery.methods.enter().send({
from: accounts[0],
value: web3.utils.toWei('1', 'ether')
});
const initialBalance = await web3.eth.getBalance(accounts[0]);
await lottery.methods.pickWinner().send({
from: accounts[0]
});
const finalBalance = await web3.eth.getBalance(accounts[0]);
const difference = finalBalance - initialBalance;
console.log(difference);
assert(difference > web3.utils.toWei('0.8', 'ether'));
});
}); 

您面临的问题是,在您尝试挑选获胜者之前,实际上从未设置过经理角色。它失败是因为在调用pickWinner()方法时,您的管理器地址为空,并且这将从restricted修饰符中的require语句中失败。我还要指出,允许任何人设置经理角色可能不是您想要做的事情。相反,您应该在部署契约时在契约构造函数中设置管理器角色,如下所示:

constructor(){
manager = msg.sender;
}

那么你可以一起去除myLottery()。希望这对你有所帮助。如果你有任何其他问题,请随时在推特上联系我@_syndk8。

最新更新