![](/img/trans.png)
[英]Eth private chain sent transaction to smartcontract error "Transaction has been reverted by the EVM"
[英]Pick Winner Lottery test throws; Error: Transaction has been reverted by the EVM:
我正在寫一份彩票合同,該合同應該接受玩家,選擇贏家並將收集到的資金發送到贏家的地址,然后重新開始。 運行 npm 運行測試后,前 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]
});
其他項目文件粘貼在下面以幫助調試。
我的 Lottery.sol 文件;
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;
}
}
編譯.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,
};
部署.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();
彩票.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()
方法時,您的經理地址是 null,並且這會因您的restricted
修飾符中的 require 語句而失敗。 我還要指出,允許任何人設置經理角色可能不是您想要做的事情。 相反,您應該在部署合同時在合同構造函數中設置經理角色,如下所示:
constructor(){
manager = msg.sender;
}
然后你可以一起擺脫myLottery()
。 希望這有所幫助。 如果您有任何其他問題,請隨時通過 Twitter @_syndk8 與我聯系。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.