I am trying to get my smart contract to transfer all its balance to another address. The transfer line doesn't throw any errors but the balance of contract does not change afterwards.
I am using web3js with ganache to test this function:
My contract:
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.12;
contract Lottery {
address payable public manager;
address payable[] public players;
constructor() {
manager = payable(msg.sender);
}
function enterLottery() public payable {
require(msg.value >= .01 ether);
players.push(payable(msg.sender));
}
function getPlayers() public view returns (address payable[] memory) {
return players;
}
function random() public view returns (uint256) {
return
uint256(
keccak256(
abi.encodePacked(block.difficulty, block.timestamp, players)
)
);
}
function pickWinner() public { // this transfer contract balance to the account
uint256 index = random() % players.length;
players[index].transfer(address(this).balance);
}
}
My test case:
beforeEach(async () => {
accounts = await web3.eth.getAccounts();
contract = await new web3.eth.Contract(abi)
.deploy({ data: evm.bytecode.object })
.send({ from: accounts[0], gas: "1000000" })
})
describe("Lottery", () => {
it("Contract has an address? ", () => {
assert.ok(contract.options.address)
})
it("Prize pool can receive ether", async () => {
await contract.methods.enterLottery().send({ from: accounts[1], gas: "1000000", value: "10000000000000000" });
const contractBalance = await web3.eth.getBalance(contract.options.address)
const hasContractReceivedEntry = contractBalance === "10000000000000000";
assert.equal(hasContractReceivedEntry, true)
})
it("Winner can receive the prize pool", async () => {
await contract.methods.enterLottery().send({ from: accounts[1], gas: "1000000", value: "10000000000000000" });
await contract.methods.pickWinner().call();
const contractBalance = await web3.eth.getBalance(contract.options.address)
console.log(contractBalance) // the contract balance should be 0 after the pickWinner call, but it is still 10000000000000000 wei the enterLottery function gave
})
})
Edit: It is confirmed that the smart contract can run enterLottery and random() as intended
CodePudding user response:
await contract.methods.pickWinner().call();
On this line, you're invoking a read-only call that doesn't update the contract state. You need to send a transaction using the .send()
function - just like on the previous line.